한가지 극단적인 예를 들어본다면,
만약 어떤 악성 프로그램이 당신의 컴퓨터에 설치가 되고 해당 프로그램을 통해서 브라우저에서 특정 명령을 수행한다면 어떻게 될까?
로그인이 세션으로 잡혀있지 않다면 로그인 작업때문에 문제가 되지 않겠지만,
세션에 로그인 정보를 저장해두었다면 로그인 정보를 가지고 특정 사이트에서 특정 명령을 수행하게 될 것이고 문제가 발생할것이다.
그래서 브라우저에서는 허용된 주소만을 받기 위해서 이 CORS를 사용할것이다.
설명을 이어서 한다면
브라우져에서는 보안적인 이유로 cross-origin HTTP 요청들을 제한한다.
그래서 cross-origin 요청을 하려면 서버의 동의가 필요하고 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절하게 된다.
이렇게 허락과 거절하는 작업을 HTTP-header를 이용해서 가능한데, 이를 CORS(Cross-Origin Resource Sharing)라고 부른다.
즉
브라우저에서 cross-origin 요청을 안전하게 할 수 있도록 하는 메커니즘
이라고 볼수 있다.
동작하는 방식은 아래 그림과 같이 동작을 한다.
cross-origin은 총 3가지를 검사하면서 허락이 된곳인지 아닌지를 판단하는데 그 3가지 조건은 다음과 같다.
- 프로토콜 - http와 https는 프로토콜이 다르다.
- 도메인 - tistory.com 과 tistory_dev.com은 다르다.
- 포트 번호 - 8080포트와 8081포트는 다르다.
이렇게 구분을 하여 CORS는 다음과 같은 방법으로 동작을 한다.
Simple requests인 경우
- 서버로 요청을 하고
- 서버의 응답이 왔을 때 브라우저가 요청한 Origin과 응답한 헤더 Access-Control-Request-Headers의 값을 비교하여 유효한 요청이라면 리소스를 응답한다. 만약 유효하지 않은 요청이라면 브라우저에서 이를 막고 에러가 발생한다.
여기서 Simple requests란?
HTTP method가 다음 중 하나이면서
- GET
- HEAD
- POST
자동으로 설정되는 헤더는 제외하고, 설정할 수 있는 다음 헤더들만 변경하면서
- Accept
- Accept-Language
- Content-Language
Content-Type이 다음과 같은 경우
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
Simple requqets라고 부른다.
이 요청은 추가적으로 확인하지 않고 바로 본 요청을 보내게 된다.
preflight 요청일 경우
- Origin헤더에 현재 요청하는 origin과, Access-Control-Request-Method헤더에 요청하는 HTTP method와 Access-Control-Request-Headers요청 시 사용할 헤더를 OPTIONS 메서드로 서버로 요청하게 된다. 이때 내용물은 없이 헤더만 전송한다.
- 브라우저가 서버에서 응답한 헤더를 보고 유효한 요청인지 확인한 후 만약 유효하지 않은 요청이라면 요청은 중단되고 에러가 발생하게 된다. 만약 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답을 받게 된다.
여기서 preflight 요청이란?
Simple requests가 아닌 cross-origin요청은 모두 preflight 요청을 하게 되는데, 실제 요청을 보내는 것이 안전한지 확인하기 위해 먼저 OPTIONS 메서드를 사용하여 cross-origin HTTP 요청을 보냅니다. 이렇게 하는 이유는 사용자 데이터에 영향을 미칠 수 있는 요청이므로 사전에 확인 후 본 요청을 보냅니다.
다음은 요청과 응답의 목록들과 예제 코드이다.
요청 헤더 목록
응답 헤더 목록
|
예제 코드
스프링부트에서 configuration을 만든후 다음처럼 지정이 가능하다.
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://127.0.0.1:8000", "http://localhost:8000") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .maxAge(3600); } |
'IT > Knowledge' 카테고리의 다른 글
ElasticSearch 란? (52) | 2022.09.20 |
---|---|
정규 표현식 정리(Regex) (59) | 2022.09.19 |
Context Switch(컨택스트 스위치) 란? (53) | 2022.09.12 |
Podman(RedHat) (43) | 2022.09.10 |
15 Factors (64) | 2022.09.08 |
댓글