網上提供了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);
}
}
