Spring/security

[시큐리티] CORS

라임온조 2023. 3. 28. 12:35

1. 개념

CORS는 cross origin resource sharing의 줄임말이다. 여기서 origin은 프로토콜(http), 도메인(naver.com), 포트번호(8080)을 합친 것을 의미한다. 즉 CORS는 서로 다른 여러 origin끼리 자원을 공유할 수 있도록 해주는 정책이다.

이는 원래대로라면 SOP에 의해 막히게 될 요청을 풀어주는 것이다.

SOP란 same origin policy의 줄임말로, 다른 origin으로 요청을 보내는 것을 금지하는 정책이다. 요즘 다른 origin으로 요청을 보내야 할 필요성이 커지자 CORS가 나타나게 된 것. 

 

예를 들어, 백엔드에서 글을 작성할 수 있는 /post/write api를 만들었다고 하자. 만약 CORS가 적용되어 있지 않는다면, SOP에 의해 /post/write api는 백엔드를 실행했을 때의 origin(https://localhost:8080/post/write)에서는 실행가능하지만, 프론트엔드가 (https://localhost:7777/post/write)라는 origin으로 접근하여 데이터를 받아와야 할 때는 실행이 불가능하다. 하지만 CORS가 적용되어 있다면 다른 origin에서도 자원을 공유할 수 있기에 백엔드와 프론트엔드에서 모두 접근가능하다.

 

2. 특징

  • CORS는 브라우저가 가지고 있는 정책이다.
    • 브라우저가 보낸 요청 혹은 브라우저가 받은 서버의 데이터가 CORS를 지키고 있는지 검사하는 것. 서버는 CORS에 상관없이 응답이 오면 요청을 하고, 이 요청을 브라우저가 중간에 받아 올바른지 확인 후 클라이언트에게 응답할지 안 할지를 결정한다.
  • 기본적으로 스프링 부트는 CORS 관련 헤더를 설정하지 않는다

 

3. 동작

기본 동작 원리는 다음과 같다. 브라우저는 어떤 origin에 요청을 보낼 때 http origin 헤더에 자신의 origin을 설정하고, 서버로부터 응답을 받으면 응답의 Access-Control-Allow-Origin 헤더에 본인의 origin이 있는지 확인한다. 만약 포함되어 있으면 cors가 올바르게 작동한다.

하지만 이러한 동작 원리는 요청의 종류에 따라 약간씩 변경된다. 

1) 헤더

Access-Control-Allow-Origin

  • cors 정책을 사용할 수 있는 origin들을 등록

Access-Control-Allow-Methods

  • cors 정책을 사용할 수 있는 origin들이 가져야 할 특정 http 방식 지정

 Access-Control-Allow-Headers

  • 특정 요청에 이용할 수 있는 헤더에 제한을 추가

2) 요청

단순 요청

  • 다양한 조건을 만족시키는 단순 요청은 안전한 요청으로 인식되어 사전 요청 없이 한 번만에 요청을 보낼 수 있다.
  • 기본 동작 원리를 따른다.

사전 요청

  • 단순 요청이 아니라고 판단된 요청은 안전하지 않은 요청으로 인식되어 서버에 실제 요청을 보내기 전에 예비 요청에 해당하는 사전 요청을 보내야 한다. 사전 요청을 보내고 난 이후 안전한 요청이라는 것이 확인되면 실제 요청을 보낸다.

인증 정보를 포함한 요청

  • 쿠키 혹은 Authorization 헤더에 설정하는 토큰과 같은 인증 정보가 있을 때를 의미한다. 

사전 요청과 인증 정보를 포함한 요청은 이 링크에 잘 설명 되어 있다.

 

4. 스프링에서 cors 사용

1) @CrossOrigin 어노테이션

  • 여러 출처를 담고 있는 배열을 매개 변수로 넘겨줄 수 있음
  • allowedHeaders 속성으로 허용되는 헤더를 설정할 수 있음
  • methods 속성으로 허용되는 메서드를 설정할 수 있음
  • 특정 메서드에 이 어노테이션을 쓰면 cors 규칙을 투명하게 확인할 수 있지만, 코드가 반복되는 경우가 생길 수 있고 새로 추가된 엔드포인트의 경우 규칙 적용을 까먹고 하지 않을 경우가 생길 수 있음
@PostMapping("/test")
@ResponseBody
@CrossOrigin("http://localhost:8080")
public String test(){
    logger.info("Test method called");
    return "HELLO";
}

2) CorsConfigurer 사용

  • cors 구성을 한 곳에서 정의
http.cors(c -> {
    CorsConfigurationSource source = request -> {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("*"));
        config.setAllowedMethods(List.of("*"));
        return config;
    };
    c.configurationSource(source);
});

 

'Spring > security' 카테고리의 다른 글

[시큐리티] OAuth 2  (0) 2023.03.30
[시큐리티] 토큰  (0) 2023.03.29
[시큐리티] CSRF  (0) 2023.03.27
[시큐리티] 필터  (0) 2023.03.23
[시큐리티] 권한과 역할제어  (0) 2023.03.21