ajax跨域問題


前言

從剛接觸前端開發起,跨域這個詞就一直以很高的頻率在身邊重復出現,一直到現在,已經調試過N個跨域相關的問題了,16年時也整理過一篇相關文章,但是感覺還是差了點什么,於是現在重新梳理了一下。

個人見識有限,如有差錯,請多多見諒,歡迎提出issue,另外看到這個標題,請勿噴~

題綱

關於跨域,有N種類型,本文只專注於ajax請求跨域(,ajax跨域只是屬於瀏覽器"同源策略"中的一部分,其它的還有Cookie跨域iframe跨域,LocalStorage跨域等這里不做介紹),內容大概如下:

  • 什么是ajax跨域

    • 原理
    • 表現(整理了一些遇到的問題以及解決方案)
  • 如何解決ajax跨域

    • JSONP方式
    • CORS方式
    • 代理請求方式
  • 如何分析ajax跨域

    • http抓包的分析
    • 一些示例

什么是ajax跨域

ajax跨域的原理

ajax出現請求跨域錯誤問題,主要原因就是因為瀏覽器的“同源策略”,可以參考

瀏覽器同源政策及其規避方法(阮一峰)

CORS請求原理

CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

基本上目前所有的瀏覽器都實現了CORS標准,其實目前幾乎所有的瀏覽器ajax請求都是基於CORS機制的,只不過可能平時前端開發人員並不關心而已(所以說其實現在CORS解決方案主要是考慮后台該如何實現的問題)。

關於CORS,強烈推薦閱讀
跨域資源共享 CORS 詳解(阮一峰)

另外,這里也整理了一個實現原理圖(簡化版):

如何判斷是否是簡單請求?

瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。只要同時滿足以下兩大條件,就屬於簡單請求。

  • 請求方法是以下三種方法之一:HEAD,GET,POST

  • HTTP的頭信息不超出以下幾種字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type(只限於三個值application/x-www-form-urlencoded、 multipart/form-data、text/plain)

凡是不同時滿足上面兩個條件,就屬於非簡單請求。

ajax跨域的表現

說實話,當初整理過一篇文章,然后作為了一個解決方案,但是后來發現仍然有很多人還是不會。無奈只能耗時又耗力的調試。然而就算是我來分析,也只會根據對應的表現來判斷是否是跨域,因此這一點是很重要的。

ajax請求時,如果存在跨域現象,並且沒有進行解決,會有如下表現:(注意,是ajax請求,請不要說為什么http請求可以,而ajax不行,因為ajax是伴隨着跨域的,所以僅僅是http請求ok是不行的)

注意:具體的后端跨域配置請看題綱位置。

第一種現象:No 'Access-Control-Allow-Origin' header is present on the requested resource,並且The response had HTTP status code 404


出現這種情況的原因如下:

  • 本次ajax請求是“非簡單請求”,所以請求前會發送一次預檢請求(OPTIONS)
  • 服務器端后台接口沒有允許OPTIONS請求,導致無法找到對應接口地址

解決方案: 后端允許options請求

第二種現象:No 'Access-Control-Allow-Origin' header is present on the requested resource,並且The response had HTTP status code 405

這種現象和第一種有區別,這種情況下,后台方法允許OPTIONS請求,但是一些配置文件中(如安全配置),阻止了OPTIONS請求,才會導致這個現象

解決方案: 后端關閉對應的安全配置

第三種現象:No 'Access-Control-Allow-Origin' header is present on the requested resource,並且status 200

這種現象和第一種和第二種有區別,這種情況下,服務器端后台允許OPTIONS請求,並且接口也允許OPTIONS請求,但是頭部匹配時出現不匹配現象

比如origin頭部檢查不匹配,比如少了一些頭部的支持(如常見的X-Requested-With頭部),然后服務端就會將response返回給前端,前端檢測到這個后就觸發XHR.onerror,導致前端控制台報錯

解決方案: 后端增加對應的頭部支持

第四種現象:heade contains multiple values '*,*'

表現現象是,后台響應的http頭部信息有兩個Access-Control-Allow-Origin:*

說實話,這種問題出現的主要原因就是進行跨域配置的人不了解原理,導致了重復配置,如:

  • 常見於.net后台(一般在web.config中配置了一次origin,然后代碼中又手動添加了一次origin(比如代碼手動設置了返回*))
  • 常見於.net后台(在IIS和項目的webconfig中同時設置Origin:*)

解決方案(一一對應):

  • 建議刪除代碼中手動添加的*,只用項目配置中的即可
  • 建議刪除IIS下的配置*,只用項目配置中的即可

如何解決ajax跨域

一般ajax跨域解決就是通過JSONP解決或者CORS解決,如以下:(注意,現在已經幾乎不會再使用JSONP了,所以JSONP了解下即可)

JSONP方式解決跨域問題

jsonp解決跨域問題是一個比較古老的方案(實際中不推薦使用),這里做簡單介紹(實際項目中如果要使用JSONP,一般會使用JQ等對JSONP進行了封裝的類庫來進行ajax請求)

實現原理

JSONP之所以能夠用來解決跨域方案,主要是因為


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM