CORS는 무엇이고, SpringBoot에서는 어떻게 처리해야하는지 정리한 내용입니다.
Protocol
,Domain/Host
,Port
3가지에 의해 결정되는 개념으로 서버의 위치를 찾아가기 위한 가장 기본적인 값들을 합친것입니다.Port
는 기본 포트 번호가 정해져있어 생략해서 쓰이는 경우가 많습니다. RFC 2616 - 3.2.2 : http URL
Browser에서 자원을 얻기 위해 최초로 요청한 곳과 같은 Origin으로 요청
하면 Same-Origin
, 하나라도 다른 곳으로 요청하면 Cross-Origin
이라 일컫습니다.
브라우저 보안상의 이유로 Script 내에서 시작된 교차 출처 HTTP 요청을 제한하는 정책입니다.
과거에는 한 사이트의 script내에서 다른 사이트에 있는 content에 접근할 수 없다는 제약이 있었습니다.
네트워크 요청
을 보낼만큼 메소드 지원도 안되고
, 단순히 웹 페이지를 꾸미기
위한 수단이었던 Javascript에 대해 개발자들이 강력한 기능을 원하면서 제약을 피하기 위한 트릭들을 만들기 시작
했습니다.
<iframe name="iframe"></iframe>
<form target="iframe" method="POST" action="http://velog.io/@sixhustle/cors">
...
</form>
Network관련 method가 없었을 때는 위의 트릭을 이용해 다른 사이트에 GET
, POST
요청을 보냈다고 합니다.
<script src="http://velog.io/@sixhustle/cors" />
Domain 제약이 없는 <script>
태그의 src
속성으로 다른 사이트에 요청을 보낼수도 있습니다.
위 방식은 보안 규칙을 깨지 않으면서 양방향으로 데이터를 전달할 수 있지만, 해커의 공격 방법으로도 사용될 수 있습니다. 자세한 내용은 ESTSecurity - DDoS 참고하시면 좋을 것 같습니다.
Browser에서 다른 출처를 가진 Resource를 안전하게 사용하는 방법입니다.
CORS는 Browser의 정책으로 Server to Server 통신에서는 발생하지 않습니다.
CORS는 Prefilght
, Simple
, Credential
3가지 요청 방식이 있고, XMLHttpRequest
, Fetch API
호출시 Site간 HTTP 요청을 허용합니다. 자세한 내용은 어떤 요청이 CORS를 사용하나요?에서 확인하실 수 있습니다.
Browser가 본 요청을 보내기 전, 본 요청을 보내기에 안전한지 확인하기 위한 예비 요청을 보내는 방식입니다.
예비 요청을 Preflight
로 부르고, 예비 요청시에는 OPTIONS
HTTP method를 사용합니다.
개발자는 Javascript언어로 Browser에게 자원을 받아오라고 명령을 내립니다.
Browser는 Header에 Origin
, Access-Control-Request-Headers
, Access-Control-Request-Method
를 추가하여 Server에게 Preflight 요청(Method: OPTIONS)을 보냅니다.
Server는 Request Header값을 보고 현재 허용하는 것인지 판단하고, 허용한다면 Access-Control-Allow-Headers
, Access-Control-Allow-Methods
, Allow-Control-Allow-Origin
, Access-Control-Max-Age
헤더 값을 추가하여 Return합니다.
Browser는 응답 헤더를 보고, 본 요청을 보내도 된다고 판단되면 Actual 요청을 보냅니다.
Server는 요청에 대한 자원과 Header값으로 Access-Control-Allow-Origin
을 응답 보냅니다.
Browser는 Access-Control-Allow-Origin
Header값을 보고, Javascript에게 자원을 넘겨줄지 정합니다.
[Preflight Response/Request Header]
[Actual Response/Request Header]
아래의 코드를 추가해주면, CORS 적용이 됩니다. 자동으로 Response Header값이 추가됩니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081")
.allowedMethods("POST", "PUT", "GET", "DELETE")
.maxAge(3600);
}
}
addMapping
: CORS를 적용할 URL패턴을 정의할 수 있습니다.
allowedOrigins
: 출처를 정하는 값입니다. *(와일드카드)
로 설정시 모든 출처에서 오는 요청을 받겠다는 의미입니다. 개발할 때 편할 수 있지만, 보안적 이슈가 발생할 수 있으므로 위와 같이 출처를 명시해주는게 좋습니다.
allowedMethods
: 허용할 HTTP Method를 지정할 수 있습니다.
maxAge
: 원하는 시간만큼 Prefilght 요청을 Caching 해둘 수 있습니다.
Config 설정 후, 응답 헤더에 Access-Control-Allow-Origin : *
이 추가된 것을 확인할 수 있습니다.