Spring Cloud Gateway CORS 문제 해결하기

Moondy·2022년 9월 14일
7

CORS란?

  • Cross Origin Resource Sharing
  • 다른 출처의 자원을 공유하는 것.
  • Spring Cloud에서는 아무것도 설정하지 않으면 보안적인 이유로 다른 출처의 HTTP 요청을 제한하는 정책을 사용하고 있다. (SOP; Same Origin Policy)
  • 하지만 Frontend, Backend 서버가 나눠져 있는 경우 등 외부에서 요청을 하게 되는 일이 발생한다. 이 때 CORS 정책을 설정해줌으로서 다른 출처의 자원에 접근할 수 있도록 하는 것이다.
  • MOZILLA에서는 CORS에 대해 다음과 같이 설명하고 있다
    Cross Origin Resource Sharing은 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 어플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제이다.

Cross-Origin이란?

  • 프로토콜이 다른 경우 (http/https)
  • 도메인이 다른 경우
  • 포트번호가 다른 경우

왜 필요할까?

  • 모든 곳에서 자원 접근이 가능하면 (데이터를 요청해서 받아갈 수 있다면) 다른 사이트에서 원래 사이트를 흉내낼 수 있기 때문에 피싱사이트를 만들어 사용자의 정보를 빼내는 등 악용할 가능성이 있다.
  • 공격을 막기 위해 필요한 경우에만 서버와 협의하여 요청할 수 있도록 하는 것이 CORS 이다.

CORS가 동작하는 3가지 시나리오

1. 단순요청 (Simple Request)

  • preflight 요청 없이 바로 요청을 보낸다
  • 아래에 명시된 메서드, Content-type, 헤더만 가능하다
  • 메서드: GET, POST, HEAD
  • Content-type
    - application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 헤더: Accept, Accept-Language, Content-Language, Content-Type 만 허용

2. 사전 요청 (Preflight Request)

  • OPTIONS메서드를 통해 다른 도메인 리소스에 요청이 가능한지 실제 요청 전에 미리 요청을 보내는 것. Preflight 요청으로 요청이 가능한 것을 확인하게 되면 실제 요청을 보낸다
  • Request에 들어갈 것
    • Origin : 요청 출처
    • Access-Control-Request-Method: 실제 요청의 메서드
    • Access-Control-Headers: 실제 요청의 추가 헤더
  • Response에 들어갈 것
    • Access-Control-Allow-Origin: 허가 출처
    • Access-Control-Allow-Methods: 허가 메서드
    • Access-Control-Allow-Headers: 허가 헤더
    • Access-Control-Max-Age: Preflight 응답 캐시 시간

Spring Cloud Gateway에서의 CORS 설정

  • Spring Cloud Gateway의 공식문서에서 제공하는 CORS 설정 방법 (바로가기)
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://front-end-domain.com"
            allowedMethods:
            - GET
            - POST

하지만 이렇게 하면 다음과 같이 에러가 난다 🤦‍♀️

원인 및 해결

1. Preflight

  • 원인
    - Spring Cloud Gateway에서 사용하는 CORS 필터는 preflight 요청일 때(OPTIONS메서드) 뒷단 서버로 보내지 않고 바로 리턴시켜 버린다.
    - 때문에 응답에 접근 허용 헤더(Access-Control-Allow-Origin)
    를 받지 못해 서버가 허용하지 않는 요청이라고 판단하여 CORS 에러가 발생한 것이다.
  • 해결
    • allowedMethods에 OPTIONS추가
    • allowedOrigins에 명시 ("*"해줘도 상관 없는데, 쿠키나 JWT 토큰을 담아 보낼 경우에는 특정해줘야한다)

2. JWT 인증요청

  • 원인
    • 쿠키 또는 JWT토큰을 담아 보낼경우 credentials: include를 포함하여 보낸다
  • 해결
    • Access-Control-Allow-Credentials:true으로 설정해줘야 인증을 포함한 요청이 가능하다
    • 이때 allowed credentials가 true인 경우, allowed_origin을 *로 입력할 수 없기 때문에 'http://localhost:3000' 이렇게 특정 origin을 입력해줘야한다. 참고블로그

      반대로 말하면, Access-Control-Allow-Credentials이 false 인 경우 allowd_origin을 "*"으로 설정하여 모든 주소를 허용할 수 있다.

3. 중복 헤더 제거

profile
DevOps를 살짝 찍먹하는 BackEnd 개발자

0개의 댓글