1. 程式人生 > >引用Spring Security 專案的跨域處理

引用Spring Security 專案的跨域處理

最近專案採用了前後端分離的框架,前端和後臺介面沒有部署到一個站點,出現了跨域問題,什麼是跨域,這裡就不再贅述,直接說解決辦法。Spring 解決跨域的方式有很多,個人採用了Crosfilter的方式。具體程式碼如下:

@Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new      UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new
CorsConfiguration(); corsConfiguration.setAllowCredentials(true); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return
new CorsFilter(urlBasedCorsConfigurationSource); }

配置完成後,測試呼叫,報錯401,依然不行。網上查資料得知,跨域請求會進行兩次。具體流程見下圖:
這裡寫圖片描述
每次跨域請求,真正請求到達後端之前,瀏覽器都會先發起一個preflight request,請求方式為OPTIONS 詢問服務端是否接受該跨域請求,具體引數如下圖:
這裡寫圖片描述
但是該請求不能攜帶cookie和自己定義的header。
由於專案中引入了Spring security ,而我使用的token傳遞方式是在header中使用authorization 欄位,這樣依賴Spring Security攔截到 preflight request 發現它沒有攜帶token,就會報錯401,沒有授權。

解決這個問題很簡單,可以使用以下配置,讓Spring security 不校驗preflight request 。

 @Override
    public void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry 
        = http.authorizeRequests();
        registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll();//讓Spring security放行所有preflight request 
    }

再試就搞定了,但是後端直接配置支援跨域會導致兩次請求。還使用另一種方式,使用Nginx 轉發一下請求也可以。