11.27 打破ajax 跨域問題,遊刃有餘的解決方案,大神就是這樣操作的

打破ajax 跨域問題,遊刃有餘的解決方案,大神就是這樣操作的

什麼是 ajax 跨域

主流的前後端分離模式下,當前端調用後臺接口時,由於是在非同一個域下的請求,從而會引發瀏覽器的自我安全保護機制,最終結果是接口成功請求並響應,但前端不能正常處理該返回數據

因此,當同時滿足以下三個條件的情況下,就會出現跨域問題:

  1. 瀏覽器限制
  2. 非同源請求(跨域)
  3. 發送的是 XHR ( XMLHttpRequest ) 請求

解決方案

打破ajax 跨域問題,遊刃有餘的解決方案,大神就是這樣操作的

想要徹底解決跨域問題,只需要破壞以上三個條件的任一即可:

1. 修改瀏覽器(不推薦

添加瀏覽器啟動參數:chrome --disable-web-security,但是極不推薦這種解決方式。

2. JSONP請求(不常用

Jsonp,全稱 JSON with Padding,一種非官方的協議,而是一種約定;前端通過向後臺發送>

所以,後臺也需要做相應的處理。以 Java 為例,添加如下配置即可:

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

public JsonpAdvice() {
// 前後端約定的jsonp參數名,默認值是callback
super("callback");
}

}

注意,Spring 4.1 版本之後,官方已不再推薦使用上述允許 jsonp 請求的配置,建議使用 CROS 配置來解決跨域問題,詳情可查看這裡

綜上,jsonp 請求存在以下幾個弊端:

  1. 服務端需要改動代碼進行支持;
  2. 只支持發送 Get 請求,請求頭中更改其它類型的請求方式是無效的;
  3. 發送的不是 XHR 請求,而是>

3. 調用方隱藏跨域

用 Nginx 或 Apache 來代理調用方的請求(客戶端變更為相對路徑請求,而非絕對路徑),此時對於瀏覽器來說,由於請求是同源的,因此就不存在跨域問題。

4. 被調用方允許跨域(最常用

  • 服務端配置

以 Java 應用為例,添加如下全局配置:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允許跨域的接口
.allowedOrigins("*") // 允許跨域的請求源
.allowedMethods("*") // 允許跨域的請求方式
.allowedHeaders("*") // 允許跨域的請求頭

.allowCredentials(true) // 帶cookie請求的時候需要開啟,且allowedOrigins需要指定為具體的請求源(最好是動態配置)
.maxAge(60 * 60 * 24); // 設定options請求預檢命令的緩存時長
}

}

如果只想針對某個類下的接口,或者是某個具體的接口配置允許跨域,只需要在相應的地方添加註解 @CrossOrigin 即可。

  • Nginx 配置

如果配置了 nginx 作為代理服務器,那麼只需要為 nginx 添加支持跨域請求即可:

 server {
listen 80;
server_name xxx.com;

location / {
proxy_pass http://localhost:8080/;

# 配置允許跨域
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;

# 對於options預檢請求,直接響應200
if ($request_method = OPTIONS) {
return 200;
}
}
}

擴展思考

打破ajax 跨域問題,遊刃有餘的解決方案,大神就是這樣操作的

Q1:瀏覽器在執行跨域請求時,是先執行後判斷,還是先判斷後執行?
A1:都有可能,這需要根據所發送的請求是簡單請求還是非簡單請求來判斷;如果是非簡單請求,瀏覽器每次在執行真正的請求之前,還會先發送一個 options 請求方式的預檢命令【

可設定緩存時長,取消每次請求都要預檢,提高效率,參考上面的服務端配置 】。關於兩種請求的區分及定義,參考下圖說明:

Q2:如果是允許帶(被調用方) cookie 的跨域請求,此時服務端同樣配置為 Access-Control-Allow-Origin 等於 *,前端是否還可以請求成功?
A2:不可以,此時要將 Access-Control-Allow-Origin 指定為調用方具體的域【 可以先取得調用方的域再動態配置,這樣就不存在多個域請求的限制問題 】,並且添加配置 Access-Control-Allow-Credentials 為 true。


我自己是一名從事了多年的前端老程序員,小編為大家準備了新出的前端編程學習資料,免費分享給大家!

如果你也想學習前端,那麼幫忙轉發一下然後再關注小編後私信【1】可以得到我整理的這些前端資料了(私信方法:點擊我頭像進我主頁有個上面有個私信按鈕)


分享到:


相關文章: