CORS(Cross Origin Resource Sharing)
다른 오리진(Cross origin)으로의 요청은 보안상의 이유로 제한된다.
요청을 정상적으로 보내려면(CORS를 하려면) 별도 추가 작업이 필요하다.
CORS 과정
from.com에서 POST to.com/myApi라는 리소스를 요청한다고 하자.
Preflight 요청
본 요청을 보내기전에 서버(b.com)가 요청하는 리소스에 CORS를 허용하는 지를 확인하는 Preflight 요청을 보낸다.
OPTIONS /myApi
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://from.com
- OPTIONS라는 특별한 메서드를 사용한다.
- Access-Control-Request-Method, Access-Control-Request-Headers, Origin 헤더가 있어야 한다.
- 이 요청을 'Preflight'라 한다.
- Preflight는 브라우저에 의해 자동으로 요청된다.(개발자는 관여하지 않는다.)
Preflight 응답 확인
CORS를 허용하는 경우 응답에 아래 헤더가 있어야 한다.
Access-Control-Allow-Origin: https://from.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type (설정값에 따라 다름)
Access-Control-Max-Age: 86400 (설정값에 따라 다름)
a.com에서 해당 API를 POST로 호출해도 좋다는 응답이다. 이후 본요청을 전송하게 된다.
만약 허용하지 않는 서버라면 응답에 위 헤더들이 없을 것이고 브라우저는 다음과 같은 에러를 뱉을 것이다.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
참고로 Preflight가 실패하면 본래의 요청 조차 보내지 않는다.
CORS 처리하기
보통 백엔드 서버만 작업하면 된다.
그러나 세션정보(쿠키)등을 같이 넘기려면 JS 작업이 필요할 수 있다.
SpringBoot에서 CORS 처리하기
옵션 1, @CrossOrigin 어노테이션 사용한다.
@CrossOrigin(origins = "https://from.com")
@PostMapping("/myApi")
public void myApi() {}
세션 정보(쿠키)를 같이 넘기려면 withCredentials를 활성화해야 한다. (js에서도 withCredentials 옵션을 줘야한다.)
@CrossOrigin(origins = "https://from.com, withCredentials = "true" )
@PostMapping("/myApi")
public void myApi() {}
withCredentials=true로 하려면 allow origin을 "*"으로 설정하면 안된다. {"a.com", "b.com"} 등으로 특정해야 한다.
옵션 2. 전역 설정
@Configuration
public WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/myApi").allowedOrigins("https://from.com");
//.allowCredentials(true) // 필요한 경우
}
};
}
}
JS에서 CORS 처리하기
특별히 할건 없다.
세션정보(쿠키)를 넘기려면 withCredentials 옵션을 줘야한다.
기본
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://to.com/myApi', true);
xhr.withCredentials = true;
xhr.send(null);
axios
const myMethod = () => {
axios.post(`https://to.com/myApi`, {
...
},
{ withCredentials: true }
).then(response => {
...
})
}
jQuery
$.ajax({
url: 'https://to.com/myApi',
xhrFields: {
withCredentials: true
}
...
});
'개발 > Spring' 카테고리의 다른 글
[Spring] 스프링 빈(Bean) 라이프사이클 (0) | 2020.05.23 |
---|---|
[Java, Spring] Filter와 Interceptor의 차이 (0) | 2020.05.22 |