Vue + SpringBoot 사용 시 CORS, CSRF

송지윤·2026년 1월 11일

Spring Boot

목록 보기
69/73

CORS란?

CORS(Cross-Origin Resource Sharing)
교차 출처 리소스 공유
브라우저가 자신의 출처가 아닌 다른 어떤 출처(도메인, 스킴 혹은 포트)로부터 자원을 로딩하는 것을 허용하도록 서버가 허가 해주는 HTTP 헤더 기반 메커니즘
또한 CORS는 교차 출처 리소스를 호스팅하는 서버가 실제 요청을 허가할 것인지 확인하기 위해 브라우저가 보내는 "사전 요청(프리플라이트, Preflight)" 메커니즘에 의존
이 사전 요청에서 브라우저는 실제 요청에서 사용할 HTTP 메서드와 헤더들에 대한 정보가 표시된 헤더에 담아 보냅니다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CORS

브라우저 보안 규칙

웹페이지가 로드된 출처(origin)가 아닌 다른 출처의 서버에 요청을 보내려면 서버가 명시적으로 허용해야 한다.

이 출처에서 오는 요청은 허용함이라고 서버가 말해줘야함
CORS는 서버에서 설정

CORS는 브라우저 보안 정책이며, 서로 다른 origin 간 요청을 허용할지 여부를 서버가 명시적으로 선언하도록 강제하는 메커니즘이다.

    // CORS 상세 설정 빈
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        
        // Vue 프로젝트가 실행되는 주소를 넣으세요 (기본적으로 5173 또는 3000)
        configuration.addAllowedOrigin("http://localhost:5173"); 
        configuration.addAllowedMethod("*"); // GET, POST, PUT, DELETE 모두 허용
        configuration.addAllowedHeader("*"); // 모든 헤더 허용
        configuration.setAllowCredentials(true); // 쿠키나 인증 정보 허용

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 적용
        return source;
    }   
  1. http://localhost:5173 에서 오는 요청은 허용한다.
  2. addAllowedMethod -> GET/POST/PUT/DELETE/OPTIONS 전부 허용
    OPTIONS : 브라우저가 prefilght 요청으로 먼저 OPTIONS를 보냄 (이게 막히면 POST는 아예 안감)
  3. addAllowedHeader -> 프론트에서 보내는 헤더 전부 허용
    (ex. Content-Type, Authorization 등)
  4. setAllowCredentials(true) -> 쿠키 / 인증정보 포함 요청 허용
    이걸 true 로 설정하면 Access-Control-Allow-Origin: * 불가
    반드시 특정 origin만 허용해야 함
  5. source.registerCorsConfiguration("/**", configuration); -> 모든 URL에 이 CORS 정책 허용

CORS 해줘야하는 이유

이게 없으면 생기는 문제
악성 사이트가 로그인된 사용자의 쿠키를 이용해 은행 API, 내부 ERP API 호출 가능
-> CSRF + 정보 탈취 위험
그래서 브라우저가 기본 차단하고 서버가 허용한 경우만 열어주는 구조

addAllowedOriginPattern

credentials 를 쓰면 왜 addAllowedOrigin 말고 addAllowedOriginPattern 을 써야하는지
credentials(true) + CORS 스펙 제약 + Spring 구현 차이 때문에

credentials가 의미하는 것

configuration.setAllowCredentials(true);

쿠키, 세션, Authorization 헤더 포함해서 요청 보내도 됨
credentials 쓰면 반드시 특정 Origin 지정해줘야함 * 전체 허용 안됨
addAllowedOrigin(*) 이런 거 안된다느 거
-> 전 세계 모든 사이트가 사용자 쿠키 들고 요청 가능

CORS 공식 스펙 규칙

Access-Control-Allow-Origin : *
Access-Control-allow-Credentials : true
이 조합은 절대 불가
addAllowedOrigin(*) 이런 거 안된다느 거
-> 전 세계 모든 사이트가 사용자 쿠키 들고 요청 가능
모든 출처에서 쿠키를 보내는 걸 허용하면 보안 붕괴
그래서 credentials=true -> 반드시 특정 origin 명시

addAllowedOrigin()의 동작 방식

요청 Origin 헤더 값 == 설정된 문자열
완전히 같아야 허용
조금이라도 다르면 차단
http://localhost:5173 이렇게 들어온 거 아니면 다 차단됨
가운데가 127.0.0.1 이거나 5173 뒤에 /붙어서 들어온다거나 https 가 들어온다거나 등등 문자 하나라도 다르면 실패
addAllowedOrigin()은 * 불가

addAllowedOrigin("http://localhost:*"); // 불가능

addAllowedOriginPattern()은 Origin을 규칙(패턴)으로 매칭한다.

addAllowedOriginPattern("http://localhost:*");

가능 모든 포트로 들어오는 거 가능

환경 분리 (실무)

# application-dev.yml
cors:
  allowed-origins: http://localhost:*

# application-prod.yml
cors:
  allowed-origins: https://www.myapp.com

CSRF 설정

Cross-Site Request Forgery
사용자가 로그인된 상태를 악용해 의도하지 않은 요청을 보내는 공격
브라우저가 자동으로 쿠키를 실어 보내는 특성을 이용한 공격

CSRF 공격 예시

  1. 사용자가 은행 사이트 로그인(쿠키 있음)
  2. 악성 사이트 접속
  3. 악성 사이트가 몰래
<form action="https://bank.com/transfer" method="POST">
  1. 브라우저가 쿠키 자동 포함
  2. 서버는 정상 사용자로 착각

CSRF가 성립하려면 반드시 필요한 조건

  1. 쿠키 기반 인증 (JSESSIONID 같은 거)
  2. 브라우저 요청
  3. 사용자가 이미 로그인된 상태
    -> 이 세 개 중 하나라도 없으면 CSRF 공격 불가

Spring Security 기본 동작

POST/PUT/DELETE 요청 시 CSRF 토큰 없으면 차단

.csrf(csrf -> csrf
    .ignoringRequestMatchers("/api/**")
)

이 경로들은 CSRF 검사 안 하겠다.

CSRF는 브라우저 + 쿠키 기반 인증에서만 의미 있음
만약 JWT, Authorization 헤더, 모바일 앱/SPA
-> CSRF 의미 거의 없음

0개의 댓글