1. 程式人生 > >全面講解AJAX跨域問題(no access-control-allow....)

全面講解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轉向不同的應用伺服器.因為是相同域名,所以不會跨域.