본문 바로가기
서버/네트워크 및 인프라

Cross-Origin Resource Sharing(CORS) 이란?

by 방구쟁이 2022. 12. 27.
728x90

 * 해당 글은 공부 및 복습 목적으로 정리하기 위한 글 입니다.

 

CORS 란?

 MDN Docs에서 CORS를 다음과 같이 정의하고 있습니다.

 CORS는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.

  보안 상의 이유로 브라우저에서 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 합니다.

 

 CORS 예제를 통해 동작하는 방식을 살펴 본 뒤 Spring 서버 설정 방법까지 알아보도록 하겠습니다. 

CORS 예제

 CORS가 동작하는 방식은 세가지가 있습니다.

 

1. Simple requests (단순요청)

 가장 간단한 접근 제어 프로토콜은 Origin 헤더와 Access-Control-Allow-Origin 을 사용하는 것입니다. Access-Control-Allow-Origin 헤더에는 요청의 Origin 헤더에서 전송된 값이 포함되어야 합니다.

 원리는 간단하지만 단순요청에 조건이 많습니다. 아래의 조건을 만족해야 단순 요청으로 전달됩니다.

     1. GET / HEAD / POST

     2. 다음 헤더일 경우에만 적용된다.
       - Accept
       - Accept-Language
       - Content-Language
       - Content-Type (아래의 추가 요구 사항에 유의하세요.)
       - DPR, Downlink, Save-Data, Viewport-Width, Width

     3. Content-Type 허용 값
       - application/x-www-form-urlencoded
       - multipart/form-data
       - text/plain

     4. 요청에 사용된 XMLHttpRequestUpload 객체에는 이벤트 리스너가 등록되어 있지 않습니다.

     5. 요청에 ReadableStream 객체가 사용되지 않습니다.

 https://foo.example의 웹 컨텐츠가 https://bar.other 도메인의 컨텐츠를 호출합니다.

Simple request


 요청 헤더의 Origin을 통해 어디에서 요청이 왔는지 확인 할 수 있습니다.

 서버는 이에 대한 응답으로 Access-Control-Allow-Origin 헤더를 전달하게 되는데 현재 Access-Control-Allow-Origin : *은 모든 도메인에서의 접근을 허용하는 것으로 https://foo.example의 요청만 허용하도록 하기 위해서는 Access-Control-Allow-Origin : https://foo.example 헤더를 전달하면 됩니다.

 

2. Preflighted requests (예비 요청)

먼저 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 미리 확인합니다.
이때 예비 요청의 HTTP 메소드는 OPTIONS메소드를 사용합니다.

  1. 다른 도메인의 리소스 요청
  2. 브라우저는 OPTIONS의 독립적인 요청 메서드로 Origin 헤더에 자신의 출처를 보낸다
  3. 브라우저는 서버의 응답 헤더 정책(응답 헤더 중 Access-Control-Allow-Origin)과 비교하여 요청이 안전하다고 판단되면 본 요청을 보낸다.
  4. 서버가 본 요청에 대한 응답을 하면 요청을 시도한 웹 컨텐츠에 전달한다.

Preflighted Request

 

3. Requests with credentials (인증 요청)

 인증된 요청은 클라이언트가 자격 인증 정보(Credential)를 실어 요청하는 방법이다. 자격 인증 정보에는 쿠키, Authorization 헤더에서 설정하는 토큰 값 등이 있다.

1) 클라이언트 설정

 클라이언트에서 인증 정보를 보내도록 하기 위해 credentials 옵션을 설정한다.

  • same-origin (default) : 같은 출처 간 요청에만 인증 정보를 담는다.
  • include : 모든 요청에 인증 정보를 담는다.
  • omit : 모든 요청에 인증 정보를 담지 않는다.
fetch('https://example.com', {
  credentials: 'include',
});


// fetch 공식문서 : https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch

 

2. 서버 헤더 설정

서버에서는 일반적인 요청과 다르게 다음 조건을 만족하는 헤더로 응답해주어야 한다.

  • Access-Control-Allow-Credentials : true
  • Access-Control-Allow-Origin, Methods, Headers : *(와일드카드 문자) 사용 불가

인증 요청

 

Spring 전역 설정

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        	.allowedOrigins("http://localhost:8080")
            .allowedMethods("POST")
            .allowCredentials(true)
            .maxAge(6000)
    }
}

 

Spring 특정 컨트롤러 설정

@Controller
@CrossOrigin(origins = "*", methods = RequestMethod.GET) 
public class testController {
    @GetMapping("/url")  
    @CrossOrigin(origins = "*", methods = RequestMethod.GET) 
    @ResponseBody
    public List<Object> findAll(){
        return service.findAll();
    }
}

 

 

참고자료

도움을 주신 분들 감사합니다.

728x90

댓글