ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Webflux - CORS
    spring 2019. 7. 31. 19:10

    개요


    Spring Webflux도 MVC와 동일하게 CORS(Cross-Origin Resource Sharing)를 지원한다. 보안 상의 이유로, 브라우저는 다른 도메인으로의 AJAX 호출을 금지한다. CORS는 도메인 간의 요청을 인증하는 것에 대한 W3C 규약으로, 대부분의 브라우저들이 이를 구현하고 있다. 여기서는 CORS 규약에 대한 자세한 설명은 하지 않고, webflux에서 관련 설정하는 법을 다루고자 한다.

     

    CORS에 대한 자세한 설명은 아래 참고

    https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

     

    설정


    Local Configuration

    어노테이션 컨트롤러 메소드에 @CrossOrigin 어노테이션을 사용하면 도메인 간 요청을 가능하게 할 수 있다.

    @RestController
    @RequestMapping("/account")
    public class AccountController {
    
        @CrossOrigin
        @GetMapping("/{id}")
        public Mono<Account> retrieve(@PathVariable Long id) {
            // ...
        }
    
        @DeleteMapping("/{id}")
        public Mono<Void> remove(@PathVariable Long id) {
            // ...
        }
    }

    위 예제에서는 '/account/{id}/'로 오는 GET 요청에 대해서만 도메인 간 요청이 허락된다.

     

    디폴트로, @CrossOrigin은 모든 도메인, header, 해당 메소드에 맵핑된 http 메소드(GET, POST, PUT 등)를 허락한다. @CrossOrigin은 또한 클래스 레벨에서도 적용 가능하다. 아래 예제는 클래스 레벨에서 특정 도메인만을 허용하는 예제로, maxAge attribute는 response header의 'Access-Control-Max-Age'의 값으로, 'preflight request'의 캐시 시간(단위: 초)이다. 클래스 레벨에서 적용하였기 때문에, 하위 모든 메소드들에 적용된다.

    @CrossOrigin(origins = "https://domain2.com", maxAge = 3600)
    @RestController
    @RequestMapping("/account")
    public class AccountController {
    
        @GetMapping("/{id}")
        public Mono<Account> retrieve(@PathVariable Long id) {
            // ...
        }
    
        @DeleteMapping("/{id}")
        public Mono<Void> remove(@PathVariable Long id) {
            // ...
        }
    }

    아래 처럼 클래스 레벨과 메소드 레벨의 @CrossOrigin을 혼합해서 사용할 수 있다. 클래스 레벨에서의 설정과 메소드 레벨에서의 설정이 모두 해당되는 메소드의 경우, 두 설정이 모두 적용이 된다.

    @CrossOrigin(maxAge = 3600) 
    @RestController
    @RequestMapping("/account")
    public class AccountController {
    
        @CrossOrigin("https://domain2.com") 
        @GetMapping("/{id}")
        public Mono<Account> retrieve(@PathVariable Long id) {
            // ...
        }
    
        @DeleteMapping("/{id}")
        public Mono<Void> remove(@PathVariable Long id) {
            // ...
        }
    }

     

    Global Configuration

    CORS 설정을 글로벌하게 적용할 수도 있다. 글로벌 설정의 경우 디폴트로 모든 origin, header, GET/HEAD/POST 메소드들을 허용한다. 디폴트로 허용하는 http 메소드의 범위가 다르다는 것이 로컬 설정과 다른 점이다. global 설정과 local 설정이 모두 존재하는 경우, 두 설정이 모두 적용된다. 그러나, maxAge처럼 하나의 값만 적용되어야 하는 경우, local 설정으로 오버라이드한다.

     

    다음은 webflux java configuration으로 CORS를 설정하는 예시이다.

    @Configuration
    @EnableWebFlux
    public class WebConfig implements WebFluxConfigurer {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
    
            registry.addMapping("/api/**")
                .allowedOrigins("https://domain2.com")
                .allowedMethods("PUT", "DELETE")
                .allowedHeaders("header1", "header2", "header3")
                .exposedHeaders("header1", "header2")
                .allowCredentials(true).maxAge(3600);
    
            // Add more mappings...
        }
    }

     

    CORS WebFliter

    MVC와 동일하게 내장된 CorsWebFilter를 적용할 수도 있다. 이는 functional endpoints 방식에 적합하다. CorsWebFilter를 빈으로 정의하고, 그 생성자에 아래 예제처럼 CorsConfigurationSource를 넘겨주면 된다.

    @Bean
    CorsWebFilter corsFilter() {
    
        CorsConfiguration config = new CorsConfiguration();
    
        // Possibly...
        // config.applyPermitDefaultValues()
    
        config.setAllowCredentials(true);
        config.addAllowedOrigin("https://domain1.com");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
    
        return new CorsWebFilter(source);
    }

     

    참고


    https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-cors

    'spring' 카테고리의 다른 글

    Reactor - Reactive Streams 생명 주기  (0) 2019.10.21
    Spring WebFlux - Config  (0) 2019.08.29
    Spring Webflux - Functional Endpoints  (0) 2019.07.25
    Spring Webflux - DispatcherHandler  (0) 2019.07.18
    Spring WebClient  (0) 2019.07.10

    댓글

Designed by Tistory.