網上提供了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,都被視為非簡單請求,即預檢請求.
簡單請求
只要同時滿足以下條件就屬於簡單請求
請求方法是以下三種方法之一: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); } }