AJAX 跨域解析

1、什麼是 AJAX 跨域問題

同源策略規定,AJAX 請求(XMLHttpRequest)只能發給同源的網址,不然就會出錯。所謂的同源策略是指 3 個相同:協議相同、域名相同、端口相同。html

好比 http://www.example.com/index.html 這個網址,協議是http ,域名是 www.example.com,端口是默認的 80。若是你在這個網站上使用 AJAX 發送 http://www.example1.com/index.html 請求,就會出錯,由於域名不一樣。前端

AJAX 跨域的根本緣由是瀏覽器不容許這麼作(不是服務端的問題),瀏覽器限制 AJAX 跨域請求的目的是爲了保證用戶信息的安全,防止數據被惡意獲取。jquery

2、JSONP 解決跨域問題

2.1 JSONP 如何解決跨域問題git

  • AJAX 請求非同源資源會發生跨域問題,可是有的 HTML 標籤支持非同源請求,舉例來講:<img src=""><script src=""> 標籤
  • 使用 JSONP 解決跨域問題,有一種方法,前端以 <script> 一樣的方式發送請求,把返回的 JSON 數據封裝,而後以 JS 腳本形式返回
  • JSONP 容許客戶端傳遞一個 callback 參數請求跨域服務端,服務端返回數據時用 callback 參數名做爲返回的函數名來包裹住返回的 JSON 數據

2.2 JSONP 示例github

這裏咱們以 MOOC 網爲例,當訪問 https://www.imooc.com/ 時,會發送一個 https://www.imooc.com/index/getstarlist AJAX 請求,下面是訪問後返回的 JSON 數據。
這裏寫圖片描述spring

咱們以 JONP 的形式(https://www.imooc.com/index/getstarlist?callback=test )訪問。
這裏寫圖片描述json

2.3 JSONP 的弊端後端

  • 須要在後端改動代碼,好比在 Spring 後臺代碼中須要配置一個 AbstractJsonpResponseBodyAdvice 切面,不過如今這個類已通過時了,也就是說如今不推薦使用 JSONP 來解決跨域問題
  • JSONP 默認只支持 GET 方式的請求
  • 發送的不是 XMLHttpRequest 請求(script),因此不支持異步事件等,不過這也是爲何 JSONP 能夠解決跨域問題的緣由

3、CORS 解決跨域問題

CORS 跨資源共享(Cross-origin resource sharing)是一種機制,它經過添加 HTTP 頭信息,解決 AJAX 跨域資源訪問問題。跨域

CORS 請求能夠分爲兩類:簡單請求與非簡單請求,主要區別是非簡單請求在進行訪問以前,會發送一個預檢請求。「預檢」請求首先經過 OPTIONS 方法向另外一域上的資源發送HTTP請求,以便肯定實際請求是否安全發送。爲了防止每次非簡單請求以前都發送預檢請求,能夠在服務端設置預檢請求的緩存的時間。瀏覽器

3.1 簡單請求

  • 請求方法爲 HEADGETPOST 中的 1 種
  • 請求的 header 中沒有自定義的請求頭
  • Content-Type 爲如下幾種:application/x-www-form-urlencodedmultipart/form-datatext/plain

3.2 非簡單請求

  • header 中包含自定義請求頭 的 AJAX 請求
  • PUTDELETE 形式的 AJAX 請求
  • Content-Type 字段的類型是 application/json

我本身在本地寫了一個測試跨域的 demo(Spring Boot),經過端口 8082 發出請求(攜帶自定義的請求頭)訪問端口爲 8081 的服務。下面是 Chrome 控制檯有關 HTTP 的控制信息。
這裏寫圖片描述
經過上面的圖能夠看出 CORS 解決跨域問題的關鍵所在,添加必要的請求頭與響應頭信息,下面是有關的頭信息介紹。

3.3 HTTP 響應首部字段

  • Access-Control-Allow-Origin:指定了容許訪問該資源的外域 URI。對於不須要攜帶身份憑證的請求,服務器能夠指定該字段的值爲通配符,表示容許來自全部域的請求。
  • Access-Control-Allow-Methods:指明瞭實際請求所容許使用的 HTTP 方法
  • Access-Control-Expose-Headers:在跨域訪問時,XMLHttpRequest 對象的getResponseHeader() 方法只能拿到一些最基本的響應頭,若是要攜帶自定義的請求頭,須要在該首部中進行容許的請求頭放入白名單
  • Access-Control-Max-Age:非簡單請求預檢命令的最大緩存時間,在緩存時間內,對於非簡單請求,不會再發送預檢請求
  • Access-Control-Allow-Credentials:是否容許攜帶身份憑證(Cookie)的請求

3.4 HTTP 請求首部字段

  • Origin:代表預檢請求或實際請求的源 URL
  • Access-Control-Request-Method:用於預檢請求。其做用是,將實際請求所使用的 HTTP 方法告訴服務器
  • Access-Control-Request-Headers:用於預檢請求。其做用是,將實際請求所攜帶的首部字段告訴服務器

4、other

能解決跨域的方式還有不少,好比禁止瀏覽器的跨域、Nginx 解決跨域等。這裏只講解了兩種常見的跨域方式,由於 JSONP 存在一些弊端,所以推薦使用 CORS 等方式來解決跨域問題。

跨域問題,涉及到不少有關 HTTP 協議 的知識,但願你們重視計算機基礎知識。上面那個測試的 demo 上傳到了 GitHub,demo 是用 Spring Boot 實現的,有須要的能夠點我前往~

參考資料

跨域資源共享 CORS 詳解l

【原創】說說JSON和JSONP,也許你會豁然開朗,含jQuery用例

Cross-Origin Resource Sharing (CORS)

相關文章
相關標籤/搜索