본문 바로가기

스프링

[스프링] CORS(Cross-Origin Resource Sharing) 해결 방법

개요

CORS(Cross-Origin Resource Sharing)란, 웹 브라우저에서 실행되는 스크립트가 다른 출처(Origin)의 서버에 접근하는 것을 제한하는 보안 기능입니다. 웹 서버에서 CORS 설정을 하지 않으면, 다른 출처에서 요청이 들어올 때 브라우저에서 차단됩니다.

CORS는 요청하는 출처와 응답하는 출처가 다를 때, 브라우저가 보안상의 이유로 데이터를 차단하는 기능입니다. 이러한 보안상의 이유는 다른 출처에서의 요청이 중요한 데이터를 탈취하거나 악성코드를 심어 보안에 침해할 수 있기 때문입니다.

 

해결방법

@CrossOrigin 어노테이션

@CrossOrigin 어노테이션은 특정 컨트롤러나 메서드에 대해 CORS를 허용하도록 설정합니다.

@RestController
public class MyController {

    @CrossOrigin(origins = "http://localhost:8080")
    @GetMapping("/hello")
    public String hello() {
        return "Hello World!";
    }
}

위 코드는 http://localhost:8080 도메인에서 온 요청만 허용합니다.

 

WebMvcConfigurer

WebMvcConfigurer 인터페이스를 구현하여 Spring MVC의 기본 동작을 변경할 수 있습니다.

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8080")
                .allowedMethods("GET", "POST")
                .allowCredentials(false)
                .maxAge(3600);
    }
}

위 코드는 모든 경로에서 http://localhost:8080 도메인에서 온 GET과 POST 요청만 허용합니다. 또한, 인증 정보를 허용하지 않으며, 최대 3600초 동안 캐시합니다.

 

Global CORS Configuration

글로벌 설정은 스프링 부트의 경우 application.properties 파일에 다음과 같이 설정할 수 있습니다.

spring.mvc.cors.allowed-origins=http://localhost:8080
spring.mvc.cors.allowed-methods=GET, POST
spring.mvc.cors.allow-credentials=false
spring.mvc.cors.max-age=3600

위 설정은 위의 WebMvcConfigurer와 동일한 설정을 적용합니다.

 

필터

CORS 요청을 처리하는 필터를 작성하여 사용할 수도 있습니다.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With, remember-me");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }
}

위 코드는 모든 도메인에서 모든 메서드를 허용합니다. 또한, 인증 정보와 함께 Authorization, Content-Type, X-Requested-With, remember-me 헤더를 허용합니다. OPTIONS 메서드를 허용하며, 응답 코드를 200으로 설정합니다.

 

CorsConfigurationSource 인터페이스 사용

이 방법은 WebMvcConfigurer를 구현하거나 @Configuration 어노테이션을 붙인 클래스를 만들어서 처리할 수 있습니다.

 @Bean
 public CorsConfigurationSource corsConfigurationSource(){
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    corsConfiguration.addAllowedOrigin("*"); // 모든 origin 허용
    corsConfiguration.addAllowedMethod("*"); // 모든 HTTP method 허용
    corsConfiguration.addAllowedHeader("*"); // 모든 header 허용
    corsConfiguration.setAllowCredentials(true); // credential 허용
    // allowCredentials 를 true로 하였을 때,
    // allowedOrigin의 값이 * (즉, 모두 허용)이 설정될 수 없도록 검증합니다.
    config.validateAllowCredentials();
    
    // 어떤 경로에 이 설정을 적용할 지 명시합니다. (여기서는 전체 경로)
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return source;
}