Spring Security Cors Mapping Error

CORS 란?

Cross-Stie HTTP Requests의 약자로 한 도메인이 다른 도메인의 자원을 사용하는 것을 의미하는데, chrome cors 기본정책이 strict-origin-when-cross-origin으로 Same Origin에 대해서만 자원을 사용하도록 제한되어 있다. 여기서 Same-Origin이란 호스트명,프로토콜,포트가 같은 도메인을 말한다.

그런데 front 서버와 back서버를 나눠 개발을 진행한 결과 두 주소(포트)가 달라 cors에러가 발생했다.

그래서 서버단에서 특정 origin을 허용할 수 있게 cors설정을 추가로 해주어야 한다.


1. Config

구글에 검색을 해보면 spring cors 문제를 해결할 방법이 filter, annotation, config로 많이 나오는데 그중 하나인 config 설정을 아래와 같이 적용해 줄 수 있다.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")      //패턴
                .allowedOrigins("*")    //URL
                .allowedOrigins("http://localhost:8080","http://localhost:8081") //URL
                .allowedHeaders("header1","header2")  //header
                .allowedMethods("GET","POST");        //method
    }
}

WebMvcConfigurer를 구현한 Config 클래스를 빈으로 등록함으로써 cors를 허용해줄 수 있는데, 위와 같은 메서드드들로 특정 URL만 cors를 허용해줄 수 있으며 “*“와 같이 작성하면 모든 URL에 대해 허용해줄 수 있다.


하지만 위와 같이 설정해주어도 cors 에러가 발생할 수 있는데 이는 우리가 프로젝트에 spring-secruity 의존성을 추가해주면서 발생한 에러이다.

spring security를 사용하게 되면 spring MVC에 도달하기 전에 spring security에서 작업을 먼저 수행하게 된다. 이때문에 spring security에서는 우리가 설정한 config는 적용이 되지못하고 security가 cors를 차단하여 에러가 발생하는 것이다.


2. Security Config 추가

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors()     //Cors 옵션 활성화
                //...다른 설정들
                ;


    }
    
    //Cors 설정
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
 }

HttpSecurity를 인자로 받는 configure메서드에서 http.cors()로 cors 옵션을 활성화 해줄 수 있다. 이때 만일 처음에 정의했던 WebMvcConfigurer 구현체가 존재한다면 corsConfigurationSource()는 추가로 정의 해줄 필요가 없고 정의를 해주지 않았다면 cors설정파일을 빈으로 등록해주어야 한다.


3. 추가 에러

java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*"since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

에러 메세지만 잘 읽어도 무엇이 문제인지 바로 알 수 있는데 spring security에서 cors설정을 할때 .addAllOrigin("*").allowCrededentials(true)를 동시에 사용할 수 없어서 나는 에러이다.

allowCredential이 true라면 “Access-Control-Allow-Origin” 응답 헤더헤더를 설정 할 수 없기 때문에 특수 값인 "*"를 사용 못하는 것이다.

해결방법은 특정 주소만 허락하거나, addAllOrigin("*") 대신 .addAllOriginPatterns("*")를 사용하면 된다.