全面講解AJAX跨域問題(no access-control-allow....)
為什麼會發生AJAX跨域問題?
瀏覽器限制(瀏覽器不允許跨域)
請求跨域(發出去的請求[其中協議,域名,埠任何一個不一樣,瀏覽器就認為是跨域的]不是本域的)
傳送的是XHR型別請求(如果不是xhr型別的請求,就算跨域,瀏覽器也不會報錯)
這三個條件同時滿足, 才有可能產生跨域安全問題.
所以跨域問題是瀏覽器校驗請求時發生的,和伺服器端沒有關係.
解決思路
允許瀏覽器跨域(不推薦 因為這是客戶端手工操作)
XHR換成JSONP(有弊端,下面會講)
跨域(讓被呼叫方修改支援跨域 或者 呼叫方修改支援跨域)
全面解決跨域問題過程
允許瀏覽器跨域(以Chrome為例) 不推薦
在Chrome的安裝目錄下 找到chrome.exe,用命令列加引數啟動(按住shift不鬆,右鍵選擇在此處開啟命令視窗
jsonp解決跨域問題(有弊端)
本次url返回結果為{"data":"get1 ok"}
ajax傳送請求的時候,預期伺服器返回的資料型別dataType填為 jsonp ,這時候傳送型別是script , 返回的是一段JS指令碼
伺服器將結果資料返回 , 將返回的資料變成JS函式的引數,函式名是前端傳參callback的值
伺服器必須增加如下的JAVA類,指定識別傳來的calback引數
不懂ControllerAdvice註解的看這裡(https://www.cnblogs.com/magicalSam/p/7198420.html)
JSONP的弊端
伺服器需要改動程式碼支援
只支援GET方法
傳送的不是XHR(XHR有很多好的特性)請求
跨域
被呼叫方解決
伺服器端實現
被呼叫方新增一個過濾器,每次請求的時候帶上允許跨域的欄位.
如果允許所有的地址呼叫 將access-Controller-allow-origin設定為*,方法同理.
簡單請求會先執行伺服器程式碼然後瀏覽器再判斷是否可以跨域 而非簡單請求瀏覽器會先發送一個預檢請求(方法型別為OPTIONS)判斷是否可以跨域,再執行伺服器程式碼.
下面是常見的簡單請求和非簡單請求
如果碰到下面這種情況,可能是非簡單請求造成的
根據報錯,在過濾器中允許跨域 res.addHeader("access-Controller-allow-headers","content-type")
快取預檢命令,提高效率,此處快取1個小時 res.addHeader("access-Controller-max-age","3600")
帶Cookie的跨域(例如8081埠想獲取8080埠的cookie, 是呼叫方獲取被呼叫方的cookie)
帶cookie的跨域,access-Controller-allow-Origin必須全匹配,不能用*,而且還要設定access-Controller-allow-Credentials為true
但這樣做又有新的問題...那就是被呼叫方只支援一個呼叫方呼叫,因為不能使用*號了.
解決方案
帶自定義頭的跨域
NGINX解決方案
hosts檔案中配置好虛擬主機後,在nginx的配置檔案中配置如下節點.
Spring框架解決
如果用的是Spring框架,Controller上直接添加註解@CrossOrigin支援跨域. Spring大法好.
NGINX呼叫方隱藏跨域
相同域名的不同URL轉向不同的應用伺服器.因為是相同域名,所以不會跨域.