WebTestClient - 带有 Spring Boot 和 Webflux 的 CORS

我有 Vuejs 前端和一个 Spring Boot Webflux 控制器。现在浏览器在调用 Spring Boot 时抱怨 CORS。

Access to XMLHttpRequest at 'https://...' from origin 'https://...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

为了启用 CORS,我尝试使用 @CrossOrigin 注释,如下所述: https://www.baeldung.com/spring-webflux-cors

但这并没有帮助,即使在控制器中使用 @CrossOrigin 注释,Spring 也不会以某种方式在响应中发回 CORS 标头。

我还按照 Bealdung 教程中的描述尝试使用 WebTestClient,它确认标题不存在:

java.lang.AssertionError: Response header 'Access-Control-Allow-Origin' expected:<[*]> but was:<null>

> OPTIONS /cors-enabled-endpoint
> WebTestClient-Request-Id: [1]
> Origin: [http://any-origin.com]
> Access-Control-Request-Method: [GET]

No content

< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Vary: [Origin, Access-Control-Request-Method, Access-Control-Request-Headers]

0 bytes of content (unknown content-type).

如果我用 response.expectHeader().exists("Access-Control-Allow-Origin"); 测试我得到:

java.lang.AssertionError: Response header 'Access-Control-Allow-Origin' does not exist

知道为什么上面链接中描述的 CORS 配置不起作用吗?我还尝试在全局配置上启用 CORS 和使用 WebFilter 启用 CORS。但似乎没有任何效果。

stack overflow WebTestClient - CORS with Spring Boot and Webflux
原文答案

答案:

作者头像

Thinice的解决方案是99.9 %。Spring WebTestClient CORS测试要求URI包含 any 主机名和端口。 actual 主机名和端口被WebTestClient忽略,以连接到测试Web服务器:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyTestClass {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void corsTest() {
        webTestClient.get()
                .uri("http://hostname-ignored:666/cors-enabled-endpoint")
                .header("Origin", "http://any-origin.com")
                .exchange()   
                .expectHeader()
                  .valueEquals("Access-Control-Allow-Origin", "*");
    }    
}

此外,可以忽略明确的端口,并且它将继续工作:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyTestClass {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void corsTest() {
        webTestClient.get()
                .uri("http://look-ma-no-port/cors-enabled-endpoint")
                .header("Origin", "http://any-origin.com")
                .exchange()   
                .expectHeader()
                  .valueEquals("Access-Control-Allow-Origin", "*");
    }
}

为了启用所有端点的COR,可以使用给定的WebFluxConfigurer:

@Configuration(proxyBeanMethods = false)
public class MyWebFluxConfigurer {

  @Bean
  public WebFluxConfigurer corsConfigurer() {
    return new WebFluxConfigurerComposite() {

      @Override
      public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
      }
    };
  }
}

*包括原始标头很重要。如果没有原点标头,则不会设置访问控制 - 允许原素的标头,并且测试将失败。

*将原点设置为与URI相同的主机名被视为相同的来源,因此未设置交叉原点标题。

  • Richart的建议是不需要专门用于启用CORS测试的Spring-boot-starter-web依赖性。

*此答案仅适用于测试。它假设您已经在服务器中启用了CORS。

*我的答案是使用Spring WebFlux 5.3.10。