文章出處

  前天面試被問到了跨域的問題,自我感覺回答的并不理想,下面我就分享一下整理后的總結分享給大家

一、為什么要跨域

  安全限制

  JavaScript或Cookie只能訪問同域下的內容——同源策略

  同源策略

  下表相對于: http://h5.jd.com/dir/ajax.js

  

  注意

  • 協議和端口造成的跨域問題,非前端解決范疇
  • 所謂域,是通過“url首部”來識別,而非判斷域與ip的對應關系

  (“URL的首部”指window.location.protocol +window.location.host)

二、跨域方案

1. jsonp

  詳見博客 JSON 和 JSONP兩兄弟

2. cors

方案對比
  JSONP CORS
目的 跨域 跨域
支持

get

(受IE下url長度不能超過2083個字節的限制和出于安全考慮,一般不用來提交數據)

所有類型的http請求
支持度 包括老式瀏覽器 不支持部分瀏覽器,移動端支持很好
缺點

1)安全問題(請求代碼中可能存在安全隱患)

2)確定jsonp請求是否失敗不太容易

3)只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題

支持率
原理

被包含在一個回調函數中的JSON

核心則是動態添加<script>標簽來調用服務器提供的js腳本

(允許用戶傳遞一個callback參數給服務端,然后服務端返回數據時會將這個callback參數作為函數名來包裹住JSON數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了)

使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功,還是應該失敗

(只需由服務器發送一個響應標頭即可)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CORS需要瀏覽器和服務器同時支持

實現CORS通信的關鍵是服務器,只要服務器實現了CORS接口,就可以跨域通信


1)兩種請求方式

  簡單請求、非簡單請求

  a)簡單請求:

  

  

  跨域時,瀏覽器自動在頭部信息中添加一個origin 字段(指定請求源-協議+域名+端口),如下圖所示

  

  服務器判斷origin在域名許可范圍內,返回響應:

  

  若不存在 Access-Control-Allow-Origin 字段,則出錯

  以上頭部信息中,CORS相關字段有

  • Access-Control-Allow-Origin
    必須字段,其值為 origin / *(可接受任意域名請求)
  • Access-Control-Allow-Credentials
    可選,是否允許發送Cookie
  • Access-Control-Expose-Headers
    可選,是否需要Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma之外的字段

  withCredentials 屬性

   CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials字段

Access-Control-Allow-Credentials: true

 

  另一方面,開發者必須在AJAX請求中打開withCredentials屬性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

 

  注意

  如果要發送Cookie,Access-Control-Allow-Origin就不能設為星號,必須指定明確的、與請求網頁一致的域名。同時,Cookie依然遵循同源政策,只有用服務器域名設置的Cookie才會上傳,其他域名的Cookie并不會上傳,且(跨源)原網頁代碼中的document.cookie也無法讀取服務器域名下的Cookie。

  b)非簡單請求(不同時滿足以上條件)

  請求方法是PUTDELETE,或者Content-Type字段的類型是application/json

   瀏覽器對于非簡單請求,就自動發出一個"預檢"請求,要求服務器確認可以這樣請求。下面是這個"預檢"請求的HTTP頭信息

  

  

  除了Origin字段,"預檢"請求的頭信息包括兩個特殊字段。

  • Access-Control-Request-Method

   該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT

  • Access-Control-Request-Headers

   該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段,上例是X-Custom-Header

 

2.CORS 支持度

 

 

3. iframe

 (只有在主域相同時才能使用)

  1)www.a.com/a.html中:

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://www.script.a.com/b.html';
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    //在這里操作doc,也就是b.html
    ifr.onload = null;
};

 

  2) 在www.script.a.com/b.html中:

document.domain = 'a.com';

 

其他跨域方案

window.name:

在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的所有頁面中的。

window.postMessage:

該方法是 HTML5 新引進的特性,可以使用它來向其它的window對象發送消息,無論這個window對象是屬于同源或不同源,目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經支持window.postMessage方法。

動態創建script

JSONP也就是利用這個原理。

利用iframe和location.hash

淘汰類技術

利用flash

淘汰類技術

 

參考鏈接:

http://tech.jandou.com/cross-domain.html

http://www.cnblogs.com/JChen666/p/3399951.html

http://www.ruanyifeng.com/blog/2016/04/cors.html

 

 

  

 


文章列表


不含病毒。www.avast.com
全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()