spring 5 webflux 功能端点请求中不存在访问控制源头

Posted

技术标签:

【中文标题】spring 5 webflux 功能端点请求中不存在访问控制源头【英文标题】:spring 5 webflux functional endpoints no access control origin header present on the request 【发布时间】:2019-03-12 08:43:35 【问题描述】:

我检查了很多资源,试图为我的问题找到正确的解决方案。从我的角度来看,我认为我拥有所需的一切,但我无法弄清楚问题出在哪里。

我正在使用 spring 5WebFlux 以及 功能端点

当我从我的 vuejs 前端发送 GET 请求时,我得到了这个:

Failed to load http://localhost:8080/test: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access. The response had HTTP status code 401.

这是请求:

OPTIONS /test HTTP/1.1 Host: localhost:8080 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Access-Control-Request-Method: GET Origin: http://localhost:8081 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Access-Control-Request-Headers: authorization Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,ro;q=0.8

我的 Spring 安全配置

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(
      ServerHttpSecurity http) 
    return http
        .authorizeExchange()
        .pathMatchers("/users/authenticate").permitAll()
        .anyExchange()
        .authenticated()
        .and()
        .httpBasic()
        .and()
        .build();
  

我尝试了几种不同的方法,这是最后两种:

1.

  private static final List<String> ALLOWED_HEADERS = Arrays.asList(
      "x-requested-with",
      "authorization",
      "Content-Type",
      "Authorization",
      "credential",
      "X-XSRF-TOKEN",
      "Access-Control-Allow-Origin",
      "Access-Control-Allow-Methods",
      "Access-Control-Allow-Headers",
      "Access-Control-Max-Age",
      "Access-Control-Request-Headers",
      "Access-Control-Request-Method");
  private static final List<String> ALLOWED_METHODS = Arrays.asList("GET", "PUT", "POST", "DELETE", "OPTIONS");
  private static final String ALLOWED_ORIGIN = "*";
  private static final String MAX_AGE = "3600";

  @Bean
  CorsWebFilter corsWebFilter() 
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowedOrigins(Collections.singletonList(ALLOWED_ORIGIN));
    corsConfig.setMaxAge(Long.valueOf(MAX_AGE));
    corsConfig.setAllowedMethods(ALLOWED_METHODS);
    corsConfig.setAllowedHeaders(ALLOWED_HEADERS);

    UrlBasedCorsConfigurationSource source =
        new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);

    return new CorsWebFilter(source);
  

2.

@Configuration
public class WebFluxSecurity implements WebFluxConfigurer 

  @Override
  public void addCorsMappings(CorsRegistry registry) 

    registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("*")
        .allowedHeaders("*")
        .exposedHeaders("Access-Control-Allow-Origin",
            "Access-Control-Allow-Methods",
            "Access-Control-Allow-Headers",
            "Access-Control-Max-Age",
            "Access-Control-Request-Headers",
            "Access-Control-Request-Method")
        .maxAge(3600);

    // Add more mappings...
  

为什么这不起作用?

【问题讨论】:

服务器似乎要求对 OPTIONS 请求进行身份验证。需要将其修复为不需要对 OPTIONS 请求进行身份验证——因为无论前端 javascript 代码发送的请求是什么,都会导致浏览器首先发出 CORS 预检 OPTIONS 请求,并且浏览器永远不会在其中包含身份验证凭据(例如,授权请求标头) CORS 预检 OPTIONS 请求。 @sideshowbarker 如您所见,我已经在 CORS 配置中添加了 OPTIONS 方法 是的,仅仅将 OPTIONS 方法添加到 CORS 配置是不够的。如果是这样,服务器将不会响应 401。在 CORS 配置之外进行一些其他更改也是必要的。例如,请参阅***.com/questions/30622624/… 的答案 【参考方案1】:

看来问题实际上不是 cors 配置。

同时我采用了一些不同的东西。

  @Bean
  public SecurityWebFilterChain securityWebFilterChain(
      ServerHttpSecurity http) 
    return http
        .authorizeExchange()
        .pathMatchers(HttpMethod.OPTIONS).permitAll()
        .anyExchange()
        .authenticated()
        .and()
        .httpBasic()
        .and()
        .build();
  

问题出在 spring 安全配置中。我只允许/users/authenticate 上的所有请求,而不是允许所有OPTIONS 方法。

我当前的 cors 配置是:

  @Bean
  CorsWebFilter corsFilter() 

    CorsConfiguration config = new CorsConfiguration();

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

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);

    return new CorsWebFilter(source);
  

【讨论】:

以上是关于spring 5 webflux 功能端点请求中不存在访问控制源头的主要内容,如果未能解决你的问题,请参考以下文章

如何使用spring webflux在功能性反应java中编写具有多个if else的复杂代码

如何在 spring-webflux RouterFunction 端点中使用 OpenApi 注释?

如何在 spring-mvc 中将日志记录添加到 webflux 端点?

Spring WebFlux WebClient 弹性和性能

将错误消息从 SSE (Webflux) Spring Boot 应用程序传递到 Angular 7 前端

将消息推送到谷歌云发布订阅后如何返回对 webflux 端点的响应?