function https(url,type,data,header,callback) {
$.ajax({
url:url,
type:type,
data:data,
contentType:'application/json',
headers:header,
crossDomain:true,
success:function (data,status) {
console.log(data);
if(data.errorNo == "20001" || data.errorNo == "20002"){
//令牌失效
window.location.href = "./lyear_pages_login.html";
}else if(data.errorNo == "0"){
callback(data,status);
}else{
alert(data.errorInfo);
}
},
error:function (XMLHttpRequest,textStatus,errorThrown) {
if(textStatus==='timeout'){
alert('請求超時');
setTimeout(function(){
alert('重新請求');
},2000);
}
window.location.href = "./lyear_pages_login.html";
}
})
}
使用改模板發送一個請求到本地服務器的時候,會出現以下的錯誤:403
General:
Request URL: http://localhost:9090/....
Request Method: OPTIONS
Status Code: 403
Remote Address: [::1]:9090
Referrer Policy: no-referrer-when-downgrade
Response Headers:
Connection: keep-alive
Date: Sat, 28 Mar 2020 07:12:49 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
Request Headers:
Provisional headers are shown
Access-Control-Request-Headers: authentication,content-type
Access-Control-Request-Method: GET
Origin: http://localhost:63342
Referer: http://localhost:63342/lyear_2_LightYear-admin/index.html
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
可以看到這個請求是OPTIONS的,而不是我們預期的GET或是POST。
原因在於:https://www.cnblogs.com/wanghuijie/p/preflighted_request.html
也就是這是一個Preflighted Request,所以發送真正的請求之前會發送一個OPTIONS請求用於試探服務器是否能接受真正的請求。如果options獲得的迴應是拒絕性質的,比如404\403\500等http狀態,就會停止post、get等請求的發出。
關於Preflighted Request(帶預檢的跨域請求)發生在:
(文檔地址:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_request_headers)
- 請求方法不是GET/HEAD/POST
- POST請求的
Content-Type
並非application/x-www-form-urlencoded
,multipart/form-data
, 或text/plain
- 請求設置了自定義的
header
字段
以上封裝的請求符合了2和3。而且在使用token驗證和大量json數據的請求中是不可避免的。
解決方法:給OPTIONS請求一個正確的響應。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
}
/**
*@Author: Czc on 2020/3/28 14:18
*@param:
*@return:
*@Description: 跨域請求配置
**/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
addCorsMappings方法對OPTIONS方法返回了允許的響應。
然後再發出真正的請求。
當然,就像登陸校驗攔截器一樣,也可以通過攔截器對請求進行處理,再響應的報文頭部中加上跨域請求相關的字段。然後對於OPTIONS請求直接截斷返回。其他的請求繼續進行。