본문 바로가기
CS

CORS

by 감자b 2024. 12. 26.

CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)

  • HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제로 웹 애플리케이션이 리소스가 자신의 출처와 다를 때 브라우저는 요청 헤더에 Origin 필드에 요청 출처를 함께 담아 교차 출처 HTTP 요청을 실행함.
  • CORS는 브라우저에 구현된 스펙으로, 브라우저가 클라이언트의 요청 헤더와 서버의 응답헤더를 비교해서 최종 응답을 결정한다.
  • 두 개의 출처를 비교하는 방법은 URL 구성요소 중에서 Protocol, Host, Port 세 가지가 모두 동일한 지 판단

CORS의 종류

1. Simple Request

  • 예비 요청(Preflight) 과정 없이 바로 서버에 본 요청을 한 후, 서버가 응답의 헤더에 Access-Control-Allow-Origin과 같은 값을 전송하면 브라우저가 서로 비교 후 CORS 정책 위반여부를 검사하는 방식.
  • 조건1. GET, POST, HEAD 중의 한 가지 메서드를 사용해야 함
  • 조건2. 헤더는 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width Width만 가능하고 나머지는 허용 X
  • 조건3. Content-Type은 application/x-www-form-urlencoded, multipart/form-data, text/plain 만 가능

위의 세 가지 제약사항을 모두 만족하면 Simple Request가 가능.

2. Preflight Request (예비 요청)

  • 브라우저는 요청을 한 번에 보내지 않고 예비 요청과 본 요청을 나누어서 전달함. 이 때 보내는 예비 요청을 Preflight라고 하며 예비 요청의 HTTP Method는 OPTIONS가 사용
  • 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 확인하는 것으로 요청 사양이 Simple Request에 해당하지 않을 경우 Preflight Request를 실행


동일 출처 판단 기준

URL (서버 URL이 “https://security.com” 이라고 가정) 동일 출처 근거
https://security.com/auth?username=userA O 프로토콜, 호스트, 포트(https 443) 동일
https://user:password@security.com O 프로토콜, 호스트, 포트 동일
http://security.com X 프로토콜이 다름
https://app.security.com X 호스트가 다름
https://security.com:8000 ? 브라우저에 따라 다름

 


CORS를 해결하려면?

서버에서 Access-Control-Allow-* 를 세팅해주어야 한다.

  • Access-Control-Allow-Origin :
    • 헤더에 작성된 출처만 브라우저가 리소스를 접근할 수 있도록 허용
    • *, “https://security.com”
  • Access-Control-Allow-Methods :
    • preflight request에 대한 응답으로 실제 요청 중에 사용할 수 있는 헤더 필드 이름을 나타냄
    • 기본값은 GET, POST, HEAD, OPTIONS, *
  • Access-Control-Allow-Headers :
    • preflight request에 대한 응답으로 실제 요청 중에 사용할 수 있는 헤더 필드 이름을 나타냄
    • 기본값은 Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Custom Header, *
  • Access-Control-Allow-Credentials :
    • 실제 요청에 쿠키나 인증 등의 사용자 자격 증명이 포함될 수 있음을 나타냄. Client의 credentials:include 일 경우 true 필수
  • Access-Control-Allow-Age :
    • preflight 요청 결과를 캐시 할 수 있는 시간을 나타내는 것으로 해당 시간동안은 preflight 요청을 다시 하지 않음

스프링 시큐리티에서 CORS 처리

  • CorsConfigurer :
    • 필터 체인에 CorsFilter를 추가
    • corsFilter 라는 이름의 빈이 있다면 해당 CorsFilter 사용, 위 빈이 없고 CorsConfigurationSource 빈이 정의되었다면 해당 CorsConfiguration이 사용
    • CorsConfigurationSource 빈이 정의되어 있지 않은 경우 Spring MVC가 클래스 경로에 있으면 HandlerMappingIntrospector 가 사용
  • CorsFilter
    • CORS 예비 요청을 처리하고 CORS 단순 및 본 요청을 가로채고, 제공된 CorsConfigurationSource를 통해 일치된 정책에 따라 CORS 응답 헤더와 같은 응답을 업데이트하기 위한 필터
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
	http
		.cors(corsConfigurer -> corsConfigurer.configurationSource(apiConfigurationSource()));
        ...
}

@Bean
CorsConfigurationSource apiConfigurationSource() {
	CorsConfiguration configuration = new CorsConfiguration();
	configuration.setAllowedOrigins(Collections.singletonList("http://localhost:5173"));
	configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
	configuration.setAllowedHeaders(Collections.singletonList("*"));
	configuration.setAllowCredentials(true);
	configuration.setMaxAge(3600L);
	configuration.setExposedHeaders(Collections.singletonList("Set-Cookie")); // JWT 토큰이라면 Authentication

	UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
	source.registerCorsConfiguration("/**", configuration); // 서비스의 모든 경로에 대해서 판단
	return source;
}

참고 : 위 코드에서 configuration.setAllowCredentials(true); 로 설정할 시 AllowedOrigin에 파라미터 와일드카드(*) 사용 불가능

'CS' 카테고리의 다른 글

OAuth2.0 개념  (1) 2025.01.02
HTTP의 이해  (0) 2024.12.27
프로세스와 스레드  (1) 2024.12.26
웹 서버, WAS, 리버스 프록시  (0) 2024.12.26
쿠키, 세션, 토큰  (0) 2024.12.26