當協議、域名、端口中任一個不同時產生跨域
CORS 跨域資源共享(Cross-origin resource sharing)
參考資料https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
CORS的兩種請求方式
簡單請求
滿足以下條件
- 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
- HTTP的頭信息不超出以下幾種字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值(application/x-www-form-urlencoded、multipart/form-data、text/plain)
流程
瀏覽器在header中增加一個Origin字段,該字段說明本次請求來自哪個源。服務器根據這個值決定是否同意這次請求。如果不允許,返回一個正常的HTTP響應,瀏覽器根據返回的響應的頭信息中是否包含Access-Control-Allow-Origin
字段判斷是否成功
非簡單請求
不滿足簡單請求的條件
流程
瀏覽器發送一個方法為OPTIONS
的預檢請求,服務器根據請求頭中的Access-Control-Allow-*
等字段判斷是否允許跨域請求。若服務器拒絕的跨域請求,會返回一個正常的HTTP響應,但是沒有任何CORS相關的信息字段。瀏覽器會認定服務器不同意預檢請求,觸發跨域錯誤。
可以通過服務端設置Access-Control-Max-Age
字段來避免頻繁發送預檢請求,單位:秒
服務端處理機制
- 首先查看HTTP頭部有無Origin字段
- 如果沒有,或者不允許,當成普通請求
- 如果有且是允許的,再看是否是
preflight(method=OPTIONS)
- 如果不是preflight(簡單請求),返回
Allow-Origin
,Allow-Credential
等字段,並返回正常內容 - 如果是preflight(非簡單請求),返回
Allow-Headers
,Allow-Methods
等
服務端的CORS解決跨域問題
在Controller上加注解 @CrossOrigin
可配置項
@AliasFor("origins")
String[] value() default {};
@AliasFor("value")
String[] origins() default {};
String[] allowedHeaders() default {};
String[] exposedHeaders() default {};
RequestMethod[] methods() default {};
String allowCredentials() default "";
long maxAge() default -1L;
統一配置
@Configuration
public class WebMvcConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");//允許任何域名
config.setAllowCredentials(true);//允許Cookie
config.addAllowedMethod("*");//允許任何方法
config.addAllowedHeader("*");//允許任何頭
config.setMaxAge(1800l);//設置預檢請求保持時間,避免頻繁發送預檢請求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
其他解決方案
vue cli3
項目根目錄下新建vue.config.js
文件
proxy: {
"/api": {
target: "http://localhost:8080/KeyWord/",// 要訪問的接口域名
}
}
在請求前加上/api/
即可,詳細參考Vue CLI3官方文檔https://cli.vuejs.org/zh/config/#devserver-proxy