zuul+security跨域Cors問題解決

zuul+security跨域Cors問題解決

簡介

場景前端

在服務後臺都會出現跨域cors問題,不過通常spring解決起來比較方便,在框架+框架的基礎上,問題就顯得特別明顯了,各類衝突,不瞭解源碼的運行原理,解決起來也是有心無力。java

這裏介紹的是zuul配置了跨域,在前端調用仍然會出現跨域的問題。git

通常沒有權限的接口加上cors配置就會經過跨域的問題。不過在服務間調用具備權限的功能,莫名的報跨域問題。github

post特殊請求web

在解決問題時發現 post 請求也有點特殊,這裏也須要處理一下。spring

post請求分爲簡單請求和複雜請求。跨域

CORS 中,可使用 OPTIONS 方法發起一個預檢請求,以檢測實際請求是否能夠被服務器所接受。預檢請求報文中的 Access-Control-Request-Method 首部字段告知服務器實際請求所使用的 HTTP 方法;Access-Control-Request-Headers 首部字段告知服務器實際請求所攜帶的自定義首部字段。服務器基於從預檢請求得到的信息來判斷,是否接受接下來的實際請求。服務器

以及 OPTIONS 未攜帶任何權限相關的內容,會被認證攔截,咱們也得放開 OPTIONS 類型請求微信

功能使用

Cross 解決

cross

以前設置很簡單,習慣操做把以前的代碼複製了過來,第一次操做是建立了一個 CorsFilter bean,可是簡單的請求確實經過了,不過權限接口過不了,因而按照一些資料配置了下面的代碼 注入了 FilterRegistrationBean bean 還設置了 order 加載順序。cors

解決後無果 仍然和以前的效果一致。

/**
 * 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Configuration
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig {

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("*"));
    config.setMaxAge(300L);

    source.registerCorsConfiguration("/**", config);
    CorsFilter corsFilter = new CorsFilter(source);
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(corsFilter);
    filterRegistrationBean.setOrder(0);
    return filterRegistrationBean;
  }
}

在一些資料+源碼的幫助下,嘗試了下面代碼:

此次實現了 CorsFilter 類 加載了 @Order 順序爲 (Ordered.HIGHEST_PRECEDENCE) 最優先。

/**
 * 解決 zuul+oauth2 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AjaxCorsFilter extends CorsFilter {

  public AjaxCorsFilter() {
    super(configurationSource());
  }

  private static UrlBasedCorsConfigurationSource configurationSource() {
    CorsConfiguration corsConfig = new CorsConfiguration();
//        List<String> allowedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
    List<String> exposedHeaders = Arrays
        .asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
//        List<String> allowedMethods = Arrays.asList("POST", "GET", "DELETE", "PUT", "OPTIONS");

    List<String> allowedHeaders = Arrays.asList("*");
    List<String> allowedMethods = Arrays.asList("*");
    List<String> allowedOrigins = Arrays.asList("*");
    corsConfig.setAllowedHeaders(allowedHeaders);
    corsConfig.setAllowedMethods(allowedMethods);
    corsConfig.setAllowedOrigins(allowedOrigins);
    corsConfig.setExposedHeaders(exposedHeaders);
    corsConfig.setMaxAge(36000L);
    corsConfig.setAllowCredentials(true);

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

哈哈哈,解決了,可是有沒有感受到莫名其妙啊,通過了解

發現其實只是一個加載順序的問題,咱們上面注入的 FilterRegistrationBean 也可使用的,只是在設置order的時候有點問題 須要設置比 security 優先級高,改成 Ordered.HIGHEST_PRECEDENCE 發現成功能夠經過跨域了。

/**
 * 跨域配置 C - Cross  O - Origin  R - Resource  S - Sharing
 *
 * @author purgeyao
 * @since 1.0
 */
@Configuration
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig {

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.setAllowedOrigins(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowedMethods(Arrays.asList("*"));
    config.setMaxAge(300L);

    source.registerCorsConfiguration("/**", config);
    CorsFilter corsFilter = new CorsFilter(source);
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(corsFilter);
    // 設置爲 Ordered.HIGHEST_PRECEDENCE
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
  }
}

解決解決。。。

OPTIONS請求解決

有關 OPTIONS(NDN
web docs)
介紹。

在發送 post 請求 會發如今真正發送以前會有一個 OPTIONS 請求。

OPTIONS 爲攜帶任何有狀態的認證信息,被權限攔截下來異常,就沒有以後的真正請求了。

咱們只須要吧 OPTIONS 請求放開 返回200狀態便可。

有不少辦法作到,能夠在zuul網關放過,也能夠經過 security 添加 忽略攔截列表。

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    ...
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
        // 添加忽略攔截OPTIONS 類型的請求
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
        ...
    }
}

options

萬事大吉。

總結

簡單的bug解決起來簡單點,不過遇到交集的bug,有心無力的感受,莫名其妙的問題,須要耐心觀察源碼運行原理。

示例代碼地址:zuul-security

做者GitHub:
Purgeyao 歡迎關注

qq交流羣: 812321371 微信交流羣: MercyYao

微信公衆號:

微信公衆號二維碼

相關文章
相關標籤/搜索