[Spring Security] Preflight는 성공하지만 실제 요청에서 CORS 오류가 발생하는 문제 해결하기

2025. 5. 26. 06:26·Spring

제목과 같이 Preflight (Options) 는 성공하지만 실제 요청에서 Cors 가 발생하는 이슈가 생겨, 이에 대해 정리한 글이다.

 

이슈 당시 확인해 본 사항

CORS 발생 당시 아래 2개 최우선으로 확인했다.

  • Access-Control-Allow-Origin 과 Access-Control-Allow-Credentials

2개를 왜 확인해야 하는지, 개념을 간략하게 정리해보면 아래와 같다.

 

Access-Control-Allow-Origin 는 없거나 다르다면 브라우저에서 응답 자체를 막아버리므로 CORS 오류가 발생한다.

Access-Control-Allow-Credentials 는 session 인증의 경우 1) 에  jwt 기반 인증의 경우 2) 에 영향을 미치며 마찬가지로 설정이 없으면 CORS 오류가 발생한다.

  1. JSESSIONID 등 쿠키 SameSite=None일 때만 cross-origin에 포함 가능
  2. Authorization 헤더 (Bearer 토큰 등) 

마지막으로 Access-Control-Allow-Origin: * 과 Access-Control-Allow-Credentials: true 를 같이 쓸 경우 모든 출처에 인증정보를 공유하는 것은 브라우저 정책상 거부되므로 CORS 가 발생한다. 따라서 credentials를 허용할 거면 반드시 명시적인 Origin을 지정해야 한다.

 

이를 위해, 서버와 클라이언트에서 다음 각각을 확인했다.

 

서버에서 Security 의 CORS 설정이 올바른지 확인했다. (Security 를 사용하지 않는다면, WebConfig 의 Cors 설정)

  • allowedOrigins 가 잘 설정되었는지
  • allowedMethods 에 누락이 없는지
  • allowedHeaders 에 지정되지 않은 헤더로 요청을 보내는지
  • allowCredentilas 를 true 로 지정했는지

여기서 추가적으로 session 기반 인증에 쿠키설정이 secure true 이므로 https 로 요청한 것이 맞는지 (로컬호스트라면  https://localhost: ) 확인했다.

 

여기까지 점검하고, 클라이언트가 axios 를 사용하고 있으므로 withCredentials 옵션을 붙였는지 확인했다.

 

확인 결과 이상이 없었다.

 

OPTIONS 와 비교

혹시 몰라 http.cors 누락도 확인해보았지만 존재하는 것으로 보아, CorsFilter 가 없어서 발생하는 문제는 아닌 것으로 판단했고, 서버 코드 어딘가에서 문제가 생겼을 것이라 추측했다. 

 

로컬서버에 요청을 넣어서 뭐가 문제인지 확인한 결과. 아래처럼 OPTIONS 에는 Access-Control-Allow-Origin 과 Access-Control-Allow-Credentials 가 있는데, POST 로 요청을 보냈을 때는 존재하지 않는 것을 확인했다.

이슈 당시 해결 방안

디버깅을 진행하기 전, 클라이언트의 원활한 작업을 위해서는 문제를 빠르게 해결해야 했기 때문에 nginx 에서 설정을 추가해 CORS 문제가 발생하지 않도록 조치했다.

 

아래처럼 map 을 이용해 cors_origin 을 지정하고 여기에 아래처럼 헤더부분에 지정하는 방식으로 구성했다.

map $http_origin $cors_origin {
    default "";
    "https://baroit.site" $http_origin;
    "https://ceo.baroit.site" $http_origin;
    ...
}

server {
    listen 443 ssl;
    server_name .site;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        add_header 'Access-Control-Allow-Origin' "$cors_origin" always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;

        if ($request_method = 'OPTIONS') {
            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain; charset=UTF-8';
            add_header 'Access-Control-Max-Age' 1728000;
            return 204;
        }
    }
}

결과적으로는  문제를 해결할 수 있었다.

 

 

왜 OPTIONS 는 성공하는데 실제 요청은 실패했을까?

nginx 구성을 통해 CORS 설정은 해결했지만, 원인을 찾지 못한 것이 걸려서 혹시? 하는 마음에 필터체인 등록순서를 확인해보았다.

 

현재 프로젝트에는 사장님 사이트와 고객사이트가 나누어져있고, 한 서버에서 처리하고 있으므로 SecurityFilter 를 아래와 같이 각각 구성해 놓은 상태다. 

 

확인 결과 CorsFilter 이전에 커스텀 필터가 위치하고 있으므로 필터 체인 등록 위치가 잘못되었음을 파악했다.

 

올바르게 아래처럼 CorsFilter 이후에 위치하도록 고치고

 

다시 확인해보면 헤더가 정상적으로 붙는다.

 

CORS 문제가 발생한다면, CORS 설정 뿐만 아니라 FilterChain 을 구성할 때 각 Filter 가 어디에 위치하는지 추가로 확인해주는 것이 좋을 것 같다. 

'Spring' 카테고리의 다른 글

[Spring] WireMock 로 Feign (ApacheHttp5Client) 테스트시 NoHttpResponseException 발생 케이스와 해결방법  (0) 2025.05.06
[Spring] TestContainers, @TestConfiguration 사용시 @DynamicPropertySource 가 적용되지 않는 문제와 해결방안  (0) 2025.04.10
[Spring] API 응답에서 직접 정의한 Error code 는 왜 사용할까?  (0) 2025.03.16
[Spring] OpenApI 3.0 Swagger 문서 작성 및 설정 방법  (1) 2025.02.11
[SpringBoot] MapStruct 제대로 활용하기  (0) 2024.11.03
'Spring' 카테고리의 다른 글
  • [Spring] WireMock 로 Feign (ApacheHttp5Client) 테스트시 NoHttpResponseException 발생 케이스와 해결방법
  • [Spring] TestContainers, @TestConfiguration 사용시 @DynamicPropertySource 가 적용되지 않는 문제와 해결방안
  • [Spring] API 응답에서 직접 정의한 Error code 는 왜 사용할까?
  • [Spring] OpenApI 3.0 Swagger 문서 작성 및 설정 방법
기억은 RAM, 기록은 HDD
기억은 RAM, 기록은 HDD
  • 기억은 RAM, 기록은 HDD
    적립식 개발
    기억은 RAM, 기록은 HDD
  • 전체
    오늘
    어제
    • 분류 전체보기 (44)
      • Gradle (1)
      • 알고리즘 (14)
        • 강한 연결 요소 (1)
        • BFS (1)
        • 다이나믹 프로그래밍 (2)
        • 그리디 (1)
        • 투 포인터 (2)
        • 비트마스크 (1)
        • 스택 (1)
        • 백트래킹 (1)
        • 유니온-파인드 (1)
        • 기초 기하학 (1)
        • 분할정복을 이용한 거듭제곱 (1)
        • 볼록 껍질 (1)
      • JPA (3)
      • Java (9)
      • Spring (8)
      • Git&GitHub (2)
      • Infra (4)
  • 최근 글

  • 인기 글

  • 태그

    자바future
    spring cors 해결
    Github
    투 포인터
    데몬쓰레드
    완전탐색
    java synchronized
    자바 runnable
    기하학
    enum정리
    자바synchronized키워드
    비트마스킹
    enum활용법
    thread 와 runnable
    java
    자바 callable
    githubworkflow
    @embedded
    정렬
    java 라이브러리 추가
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.1
기억은 RAM, 기록은 HDD
[Spring Security] Preflight는 성공하지만 실제 요청에서 CORS 오류가 발생하는 문제 해결하기
테마상단으로

티스토리툴바