Webflux 跨域设置及与权限冲突的解决办法

网上提供了2种跨域的设置方式

  1为 重写 WebFluxConfigurer 的 addCorsMappings。

  2为 提供一个 WebFilter 或 CorsWebFilter。

  注意点,如果有权限验证的filter,建议使用第二种凡是,且CorsWebFilter一定要优先于AuthFilter过滤,否则跨域的PreFilght将一直失败,无法实现跨域。

   Cors原理如下:

   浏览器将cors请求分为两类即简单请求和非简单请求.
   简单请求
   只要同时满足以下条件就属于简单请求
   请求方法是以下三种方法之一:GET POST HEAD
   Http的头信息不超出以下几种字段:Accept Accept-Language Content-Language Last-Event-ID Content-Type 只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
   非简单请求
   其他的请求皆属于非简单请求.
   注意在cors定义中,如果头信息中的Content-Type不设置,则默认值为json/application,如果Content-Type值不为application/x-www-form-urlencoded,multipart/form-data或text/plain,都被视为非简单请求,即预检请求.

   浏览器对这两种请求的处理是不一样的.
   如果是简单请求的话,一次完整的请求过程是不需要服务端预检的,直接响应回客户端。
   而非简单请求则浏览器会在发送真正请求之前先用OPTIONS发送一次预检请求preflight request,从而获知服务端是否允许该跨域请求,当服务器确认允许之后,才会发起真正的请求.
 
   那么带有权限的非简单请求,首先要触发了一次预检请求,但由于服务端使用了权限认证框架,通过拦截用户请求头中传过来的token信息来判定客户端是否为非法调用,而Preflight请求过程中并不会携带我们自定义的token信息到服务器,这样服务器校验就永远也无法通过了,就算是合法的登录用户也会被拦截.
 
  附:CorsWebFilter代码
   
/**
 * 跨域Filter
 */
@Configuration
@Data
public class CorsFilter implements WebFluxConfigurer {

    @Value("#{'${cors.allowedOrigins:*}'.split(',')}")
    private List<String> allowedOrigins;
    @Value("#{'${cors.allowedHeaders:*}'.split(',')}")
    private List<String> allowedHeaders;
    @Value("#{'${cors.allowedMethods:*}'.split(',')}")
    private List<String> allowedMethods;
    @Value("${cors.corsMapping:/**}")
    private String corsMapping;

    /**
     * corsWebFilter需要早于AuthFiler
     */
    @Bean
    @Order(-200) //非常重要,一定要早于AuthFilter
    CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        for(String val:allowedOrigins){
            config.addAllowedOrigin(val);
        }
        for(String val:allowedHeaders){
            config.addAllowedHeader(val);
        }
        for(String val:allowedMethods){
            config.addAllowedMethod(val);
        }
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration(corsMapping, config);
        return new CorsWebFilter(source);
    }
}

  



原文地址:https://www.cnblogs.com/gxiaoyang/p/13610839.html