在公司開發程序中,第一次做前后端分離的專案就遇見了跨域的問題,
前端控制臺報錯:No 'Access-Control-Allow-Origin' header is present on the requested resource.
百度得知:spring boot解決跨域問題,兩種解決方法:
1、重寫 WebMvcConfigurer 類,并注入到spring容器中:
@Configuration public class CustomCorsConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT") .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers") .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials") .allowCredentials(true).maxAge(3600); } }
這個底層我猜想是一種攔截器,他的優先級在過濾器之后,也就是說執行完過濾器,才會執行這個攔截器,
2、在@Configuration中,注入CorsFilter:
@Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig()); return new CorsFilter(source); } private CorsConfiguration corsConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); // 請求常用的三種配置,*代表允許所有,也可以自定義屬性(比如 header 只能帶什么,只能是 post 方式等) corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); return corsConfiguration; }
這個底層就是過濾器,想要獲得服務器的跨域允許,必須經過此攔截器,
不過,在嘗試了兩種方法發現,why?我的專案還是報錯:No 'Access-Control-Allow-Origin' header is present on the requested resource.
在使用第二種方法,并經過除錯后發現了問題,CorsFilter 的執行順序在token過濾器的后面!

這時候再來了解下跨域的原理,詳見 http://www.ruanyifeng.com/blog/2016/04/cors.html
我這邊前端是屬于跨域中的非簡單請求,他的程序是:在前端真正發送請求api介面的http時,會發出一個類似于嗅探的假請求給服務器,這個假請求會從服務器攜帶資訊,告知頁面是否允許頁面跨域訪問,如果允許,則發出真正的http,如果不,瀏覽器控制臺直接報錯,
我這個專案的問題就出在這,如果這個嗅探沒到達CorsFilter,就被服務器攔截下來了,那么他得到的資訊肯定是 不允許跨域訪問 ! 我們的嗅探就是被專案中的jwt過濾器攔截下來了,因為我在專案中的設定是每個請求必須攜帶jwt的token,否則被攔截下來,而嗅探是一種瀏覽器生成的簡單請求,肯定不攜帶jwt token,因此被攔截下來了,也就沒法到達CorsFilter,就沒法獲得跨域的許可,所以在使用百度的第二種方法就失敗了!
那么第一種百度的方法失敗的原因呢?更簡單了!因為第一種底層是攔截器(WebMvcConfigurer),他的執行優先級在過濾器之后,所以嗅探的http在到這個攔截器的時候,早就被jwt過濾器擋下來了,因此提示跨域失敗!
聽了上述分析,是否解決思路已經有了呢?對,只要我們的嗅探http到達CorsFilter過濾器或者攔截器(WebMvcConfigurer)就行了,但是我們的jwt過濾必須得要,所以我的解決方法是,修改CorsFilter的優先級:
@Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig()); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); //*****這里設定了優先級***** bean.setOrder(1); return bean; } private CorsConfiguration corsConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); // 請求常用的三種配置,*代表允許所有,也可以自定義屬性(比如 header 只能帶什么,只能是 post 方式等) corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); return corsConfiguration; }

完美解決!
最后想說的是百度的方法是有用的,但是不同的專案環境不一樣,所以不一定能生效,要結合環境來具體使用!
如有不對的地方,還望讀者指出!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/180076.html
標籤:其他
下一篇:Java設計模式
