跨域問題及解決思路

形成跨域的兩種策略

瀏覽器的同源策略會致使跨域,這裏同源策略又分爲如下兩種javascript

  1. DOM同源策略:禁止對不一樣源頁面DOM進行操做。這裏主要場景是iframe跨域的狀況,不一樣域名的iframe是限制互相訪問的。
  2. XmlHttpRequest同源策略:禁止使用XHR對象向不一樣源的服務器地址發起HTTP請求。
只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域,之間的請求就是跨域操做。

 

爲何要有跨域限制

瞭解完跨域以後,想必你們都會有這麼一個思考,爲何要有跨域的限制,瀏覽器這麼作是出於何種緣由呢。其實仔細想想就會明白,跨域限制主要是爲了安全考慮。html

 

AJAX同源策略主要用來防止CSRF攻擊。若是沒有AJAX同源策略,至關危險,咱們發起的每一次HTTP請求都會帶上請求地址對應的cookie,那麼能夠作以下攻擊:java

  1. 用戶登陸了本身的銀行頁面 http://mybank.comhttp://mybank.com向用戶的cookie中添加用戶標識。
  2. 用戶瀏覽了惡意頁面 http://evil.com。執行了頁面中的惡意AJAX請求代碼。
  3. http://evil.comhttp://mybank.com發起AJAX HTTP請求,請求會默認把http://mybank.com對應cookie也同時發送過去。
  4. 銀行頁面從發送的cookie中提取用戶標識,驗證用戶無誤,response中返回請求數據。此時數據就泄露了。
  5. 並且因爲Ajax在後臺執行,用戶沒法感知這一過程。

 

DOM同源策略也同樣,若是iframe之間能夠跨域訪問,能夠這樣攻擊:ajax

  1. 作一個假網站,裏面用iframe嵌套一個銀行網站 http://mybank.com
  2. 把iframe寬高啥的調整到頁面所有,這樣用戶進來除了域名,別的部分和銀行的網站沒有任何差異。
  3. 這時若是用戶輸入帳號密碼,咱們的主網站能夠跨域訪問到http://mybank.com的dom節點,就能夠拿到用戶的輸入了,那麼就完成了一次攻擊。

因此說有了跨域跨域限制以後,咱們才能更安全的上網了。json

 

跨域的解決方式

> 跨域資源共享

CORS是一個W3C標準,全稱是」跨域資源共享」(Cross-origin resource sharing)。 對於這個方式,阮一峯老師總結的文章特別好,但願深刻了解的能夠看一下http://www.ruanyifeng.com/blog/2016/04/cors.html後端

這裏我就簡單的說一說大致流程。api

  1. 對於客戶端,咱們仍是正常使用xhr對象發送ajax請求。
    惟一須要注意的是,咱們須要設置咱們的xhr屬性withCredentials爲true,否則的話,cookie是帶不過去的哦,設置: xhr.withCredentials = true;
  2. 對於服務器端,須要在 response header中設置以下兩個字段:
    Access-Control-Allow-Origin: http://www.yourhost.com
    Access-Control-Allow-Credentials:true
    這樣,咱們就能夠跨域請求接口了。

> jsonp實現跨域

基本原理就是經過動態建立script標籤,而後利用src屬性進行跨域。跨域

這麼說比較模糊,咱們來看個例子:瀏覽器

// 定義一個fun函數 function fun(fata) { console.log(data); }; // 建立一個腳本,而且告訴後端回調函數名叫fun var body = document.getElementsByTagName('body')[0]; var script = document.gerElement('script'); script.type = 'text/javasctipt'; script.src = 'demo.js?callback=fun'; body.appendChild(script); 

返回的js腳本,直接會執行。因此就執行了事先定義好的fun函數了,而且把數據傳入了進來。安全

fun({"name": "name"}) 

固然,這個只是一個原理演示,實際狀況下,咱們須要動態建立這個fun函數,而且在數據返回的時候銷燬它。

由於在實際使用的時候,咱們用的各類ajax庫,基本都包含了jsonp的封裝,不過咱們仍是要知道一下原理,否則就不知道爲何jsonp不能發post請求了~

> 服務器代理

瀏覽器有跨域限制,可是服務器不存在跨域問題,因此能夠由服務器請求所要域的資源再返回給客戶端。

 

服務器代理是萬能的。

> document.domain來跨子域

對於主域名相同,而子域名不一樣的狀況,可使用document.domain來跨域 這種方式很是適用於iframe跨域的狀況,直接看例子吧 好比a頁面地址爲 http://a.yourhost.com b頁面爲 http://b.yourhost.com。 這樣就能夠經過分別給兩個頁面設置 document.domain = http://yourhost.com 來實現跨域。 以後,就能夠經過 parent 或者 window[‘iframename’]等方式去拿到iframe的window對象了。

 

使用window.name進行跨域

window.name跨域一樣是受到同源策略限制,父框架和子框架的src必須指向統一域名。window.name的優點在於,name的值在不一樣的頁面(或者不一樣的域名),加載後仍然存在,除非你顯示的更改。而且支持的長度達到2M.

//a頁面的代碼 <script type="text/javascript"> iframe = document.createElement('iframe'); iframe.style.display = 'none'; var state = 0; iframe.onload = function() { if(state === 1) { var data = iframe.contentWindow.name; console.log(data); iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); } else if(state === 0) { state = 1; iframe.contentWindow.location = 'http://m.zhuanzhuan.58.com:8887/b.html'; } }; document.body.appendChild(iframe); </script> 

 

//b頁面代碼 <script type="text/javascript"> window.name = "hello"; </script> 

 

> location.hash跨域

location.hash方式跨域,是子框架具備修改父框架src的hash值,經過這個屬性進行傳遞數據,且更改hash值,頁面不會刷新。可是傳遞的數據的字節數是有限的。

//a頁面的代碼 <script type="text/javascript"> iframe = document.createElement('iframe'); iframe.style.display = 'none'; var state = 0; iframe.onload = function() { if(state === 1) { var data = window.location.hash; console.log(data); iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); } else if(state === 0) { state = 1; iframe.contentWindow.location = 'http://m.zhuanzhuan.58.com:8887/b.html'; } }; document.body.appendChild(iframe); </script> 

 

//b頁面代碼 <script type="text/javascript"> parent.location.hash = "world"; </script> 

 

> 使用postMessage實現頁面之間通訊

信息傳遞除了客戶端與服務器以前的傳遞,還存在如下幾個問題:

  • 頁面和新開的窗口的數據交互。
  • 多窗口之間的數據交互。
  • 頁面與所嵌套的iframe之間的信息傳遞。

window.postMessage是一個HTML5的api,容許兩個窗口之間進行跨域發送消息。這個應該就是之後解決dom跨域通用方法了,具體能夠參照MDN。

補充: 其實還有一些方法,好比window.name和location.hash。就很適用於iframe的跨域,不過iframe用的比較少了,因此這些方法也就有點過期了。

這些就是我對跨域的瞭解了,實際狀況下,通常用cors,jsonp等常見方法就能夠了。不過遇到了一些很是規狀況,咱們仍是須要知道有更多的方法能夠選擇的

相關文章
相關標籤/搜索