본문 바로가기
문제 해결 기록

[Spring boot X Spring Security] CORS 설정하기

by 타태 2022. 3. 21.

2022.03.14 - [실전 공부/Java&Spring&SpringBoot] - [REACT x SPRING BOOT] Axios + multipart/form-data 깔끔하게 받기 (파일 + 게시물 동시에 받기)

 

[REACT x SPRING BOOT] Axios + multipart/form-data 깔끔하게 받기 (파일 + 게시물 동시에 받기)

2022.02.22 - [실전 공부/AWS&Docker&Linux] - [Docker] Layered jar를 이용한 스프링 부트 Docker build 최적화 [Docker] Layered jar를 이용한 스프링 부트 Docker build 최적화 스프링 부트 메이븐 플러그인..

ktae23.tistory.com

 

스프링부트 환경에서 스프링 시큐리티까지 사용한다면 CORS 설정을 두 번 해야 한다.

한번은 스프링 전역 설정을 위한 WebMvcConfigurer 구현 클래스,

또 한번은 시큐리티 설정을 위한 WebSecurityConfigurerAdapter 구현 클래스이다.

 

WebMvcConfigurer 구현 클래스 (Spring CORS config)

@Configuration
public class WebConfig implements WebMvcConfigurer {
	@Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            // 메서드 허용
            .allowedMethods(
            		HttpMethod.POST.name(), HttpMethod.GET.name(), 
            		HttpMethod.PUT.name(), HttpMethod.DELETE.name(), 
            		HttpMethod.OPTIONS.name()
                )
            // 요청 헤더 허용
            .allowedHeaders("Authorization", ...)
            // 응답 헤더 허용
            .exposedHeaders("Authorization", ...)
            // 오리진 허용
            .allowedOrigins(허용 오리진);
    }
}

 

 

 

WebSecurityConfigurerAdapter 구현 클래스 (Spring Security CORS Config)

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(org.springframework.security.config.annotation.web.builders.WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**", "/dist/**", "/css/**", 
        "/fonts/**", "/favicon.ico", "/img/**", "/js/**, ...");
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
       		.....
        	// preFlight 요청 허용
            .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
            .and()
            // cors 설정 추가
            .cors().configurationSource(corsConfigurationSource())
            ......	
    }
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {

        CorsConfiguration configuration = new CorsConfiguration();
        // 쿠키 사용 허용
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(오리진 설정);
        // 메서드 허용
        configuration.setAllowedMethods(
        	Arrays.asList(HttpMethod.POST.name(), HttpMethod.GET.name(), 
                        HttpMethod.PUT.name(), HttpMethod.DELETE.name(), 
                        HttpMethod.OPTIONS.name())
        );
        // 요청헤더 허용
        configuration.setAllowedHeaders(
        	Arrays.asList("Authorization", ...)
        );
        // 응답 헤더 허용
        configuration.setExposedHeaders(
        	Arrays.asList("Content-Type", ...)
        );
        
        UrlBasedCorsConfigurationSource source 
        	= new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        FilterRegistrationBean bean 
        	= new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return source;
    }
}

 

 

두 클래스의 구분은 시큐리티 필터를 타느냐 아니냐의 기준으로 설정해준다.

위 시큐리티 설정 클래스를 보면 "/css/**", "/js/**" 등과 같은 리소스 경로들은 시큐리티 필터에서 제외하도록 web.ignoring().antmatchers() 안에 설정을 해두었다.

이처럼 시큐리티 필터를 타지 않는 요청의 경우 스프링 전역 설정에 영향을 받는다.

이 외에 시큐리티 필터를 타는 요청의 경우 스프링 시큐리티 설정에 영향을 받는다.

 

때문에 시큐리티 제외 요청에서 CORS 에러가 난다면 WebMvcConfigurer 구현 클래스에서 설정을 해야하고,

시큐리티 필터 요청에서 CORS 에러가 난다면 WebSecurityConfigurerAdapter 구현 클래스에서 설정을 해야 한다.

 

이 외에도 컨트롤러에 직접 CORS를 설정하여 적용해주어도 된다.

더 자세한 설정일수록 우선 순위를 갖기 때문이다.

 

Controller 직접 설정

@CrossOrigin(origins = "*", exposedHeaders = {"Content-Disposition"})
public class TestController {

	.....
}

 

 

반응형

댓글