CORS관련Spring Security흐름브라우저 ↓ Spring Security Filter Chain ↓ DispatcherServlet ↓ WebMvcConfigurer(CorsConfig) ↓ Controller
필터 레벨 CORS 설정:WAS에서요청수신 시필터체인에 의해CORS 처리 활성화및 검증 수행
Spring MVC 레벨 CORS 설정:Dispatcher Servlet이후WebMvcConfigurer에서CORS 정책설정
▶WebMvcConfigurer에서 설정된CORS 정책을 기반으로필터 레벨에서요청을 검증
필터 레벨에서 FilterChain의CORS관련 설정
。SecurityFilterChain관련@Configuration 클래스에서 설정을 수행
。Spring Security에서는 기본적으로 다른Origin으로부터의Cross-Origin Request를 차단
▶필터 레벨에서CORS 관련 설정을 수행하지 않는 경우,Spring Security Filter에 의해 다른출처의브라우저로부터의요청을 차단httpSecurity.authorizeHttpRequests( auth -> auth .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // )。
요청시인가검사를 수행하는 경우Preflight Request에 대해 모두 허용하도록 설정.
httpsecurity객체.cors(콜백함수)
。HttpRequest에 대한CORS 정책을 지정하는메서드
▶WebMvcConfigurer를 통한CORS 정책을 지정하도록 설정이 가능@Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity){ return httpSecurity .cors(Customizer.withDefaults()) // ... }
httpSecurity객체.cors(cors-> cors.disable())
。필터레벨에서의CORS 활성화를 차단하여 모든출처로 부터의요청을 허용
▶운영환경에서는 반드시 지양해야하며 오직개발 환경에서만 수행
httpSecurity객체.cors(Customizer.withDefaults())
。CORS에 관련된Spring 기본 설정으로 설정하면서CORS 활성화
▶withDefaults()는Customizer Class의정적메서드
。해당 기능 설정 시Spring MVC 레벨에서의WebMvcConfigurer에서 설정한CORS 정책을Spring Security가 참고 후필터에서검증을 통해Cross-Origin Request의요청 허용
▶CORS 정책에서 설정된Origin, Method, Header등을 기반으로요청을검증후허용
CORS Configuration종류
。Spring MVC활용 시Cross-Origin Request허용하는 기법
。전역으로 설정하는Global Configuration과Local Configuration이 존재.
Global Configuration:
。어플리케이션내 모든Controller,REST Controller에 설정된CORS 정책을 일괄적으로 적용하도록 설정
WebMvcConfigurer를 통해CORS 정책을 정의 후Spring Bean로서 등록
。CORS 정책을 정의한WebMvcConfigurer 구현체를Spring Bean으로 등록 시Spring Security가 참고 후필터에서요청을 검증
▶addCorsMappings() 구현메서드를 익명클래스 방식으로 구현한구현체생성 후Spring Bean으로 등록
。CORS Configuration된WebMvcConfigurer의 instance를 Spring Bean으로 반환하는@Bean Method구현.import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class BasicAuthSecurityConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { // addCorsMappings()를 Override하여 작성하며 // 매개변수로 전달된 CorsRegistry instance를 통해 Cross-Origin Request의 CORS Configuration 수행. public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 모든 URL Pattern에 대하여 CORS 허용. .allowedMethods("*") // 모든 HTTP Method에 대하여 CORS 허용 .allowedOrigins("http://localhost:3000") // React의 Origin에 대해서만 CORS 허용. .allowedHeaders("*") .allowCredentials(true) .exposedHeaders("Authorization") .maxAge(3600); } }; } }。
익명클래스방식을 통해addCorsMappings()를오버라이딩하여WebMvcConfigurer 인터페이스 구현체를 생성 및Spring Bean으로 등록
WebMvcConfigurer
。Spring MVC의 세부적인Configuration을사용자 정의하는구현 메서드를 제공하는인터페이스
。Spring Boot은 기본적으로Auto Configuration을 제공하지만, 세부설정이 필요할 경우WebMvcConfigurer을 통해 정의.
▶인터페이스 구현체를Spring Bean으로 등록하면서CORS Configuration,Interceptor 추가,Static Resource Mapping,View Controller Configuration를 수행
。Security 설정을 수행한WebMvcConfigurer 구현체를Spring Bean으로 등록 시Spring Security가 참고 후필터에서요청을 검증
WebMvcConfigurer 구현 메소드종류
addCorsMappings(CorsRegistry registry)
。Spring에서CORS정책을 설정하는WebMvcConfigurer 구현 메서드
▶ 특정Origin의Cross-Origin Request를어플리케이션내컨트롤러에서전역적으로 허용하도록 설정 가능
。CorsRegistry 객체를 매개변수로 가져오므로, 해당CorsRegistry객체를 이용해CorsRegistry의 Method를 활용하여CORS정책을 설정.
CorsRegistry:
。WebMvcConfigurer의addCorsMappings() 구현메서드에 의해Spring MVC에서CORS 정책을 설정 시 사용하는클래스
▶WebMvcConfigurer Interface의addCorsMappings(CorsRegistry registry) 메서드를 통해CORS 정책을 지정
CorsRegistryMethod
。해당메서드를 통해CORS 정책을 지정
CorsRegistry객체.allowedOrigins("Origin1", "Origin2" , ...)
。Spring Boot에서CORS를 허용할Origin을 지정하는 Method.
CorsRegistry객체.allowedOrigins("http://localhost:3000")
。특정Origin에 대해서만CORS허용.
CorsRegistry객체.allowedOrigins("*")
。모든Origin에 대해서CORS허용.
▶Origin은화이트리스트방식을 통해 지정해야하므로, 반드시 지양
CorsRegistry객체.addMapping("/URLpattern")
。Origin을 기반으로Cross-Origin Request의CORS를 허용할URL 패턴을 지정.
ex )CorsRegistry객체.addMapping("/api/**"):
。Origin/api/로 시작하는 모든Cross-Origin Request에 대하여CORS허용
CorsRegistry객체.allowedMethods("GET", "POST" , ...)
。Cross-Origin Request에서CORS를 허용할HTTP Method지정.
▶"GET","POST","PUT","DELETE","PATCH"
CorsRegistry객체.allowedHeaders("Content-Type" , "Authorization" , ...)
。Cross-Origin Request에서CORS를 허용할Header를 지정하는 Method.
CorsRegistry객체.allowedHeaders("*"): 모든header에 대해서CORS허용.
CorsRegistry객체.allowCredentials(Boolean)
。Cookie,세션등의인증정보를 포함한Cross-Origin Request에 대하여CORS허용여부 설정.
▶쿠키 / 세션을 사용하지 않는 경우 설정하지 않아도 된다.
ex )인증 헤더를 사용하는JWT 토큰
。Refresh Token을HttpOnly 쿠키로 전달 및 요청하는 경우 반드시활성화
。CorsRegistry객체.allowCredentials(true)설정 시CorsRegistry객체.allowedOrigins("*")를 사용할 수 없으며, 반드시특정 Origin만 지정하여 설정해야한다.
CorsRegistry객체.exposedHeaders("Authorization")
。브라우저의Javascript가Authorization Header에 포함된데이터를 읽을 수 있도록 설정.
▶브라우저는CORS에 의해 기본적으로HTTP Response의헤더를JS에 의해 읽을 수 없도록 설정하므로, 허용하도록 설정해야한다.
。주로JWT 토큰을HTTP Response의Authorization Header로 응답 시 사용
CorsRegistry객체.maxAge(초)
。CORS의Preflight 요청 결과를브라우저가 얼마나캐싱할지 설정.
▶캐싱한결과를 기준으로동일한 Origin에서동일한 요청 메서드를 사용해요청시Preflight Request를 생략함으로써 성능 향상
Local Configuration:
。특정Controller,REST Controller에@CrossOrigin을 선언하여Cross Origin Request를 허용설정.
▶Global Configuration와 달리 특정Controller에만 국한.
@CrossOrigin
。Spring Framework에서CORS를 허용하는 용도의어노테이션으로origins를 통해 정의된 도메인으로부터의Cross-Origin Request의 허용여부를 결정.
▶@Controller,@RestController가 선언된 Class 앞에 정의하여origins속성에 의해 허용된 도메인으로부터 해당Controller의API호출시CORS를 허용.
。origins="URL"속성을 통해서Cross-Origin Request를 허용할 특정 도메인을 지정.
▶origins속성을 지정하지 않는 경우 모든 도메인으로부터의Cross-Origin Request를 허용.import org.springframework.web.bind.annotation.*; import java.util.List; @RestController // Controller Class에 Cross Origin 선언. @CrossOrigin(origins="http://localhost:3000") public class Security_Filter_Chain { @GetMapping(path="/todos") public List<Todo> returnTodos(){ return TODOS; } }