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

+ Recent posts