同源策略和跨域解決方法

第一部分:同源策略:same-origin policyjavascript

1.同源策略的由來:php

1995年,同源策略由Netscape(曾經的瀏覽器霸主,拒絕微軟收購請求,被IE給整垮。如今發展爲火狐瀏覽器背後的Mozilla)引入。目前,全部瀏覽器都遵循同源策略html

 

2.同源定義:即同協議、同域名、同端口號java

例如:http://www.test.com:80/test.html;     協議:http;域名:www.test.com;端口號:80(默認端口,能夠省略)web

http://www.test.com/test100.html    (同源)
http://test.com/test100.html      (不一樣源,域名不一樣)
http://x.www.test.com/test100.html  (不一樣源,域名不一樣)
http://www.test.com:81/test100.html  (不一樣源,端口號不一樣)
https://www.test.com/test100.html  (不一樣源,協議不一樣)ajax

可是在IE瀏覽器上端口號不一樣被認爲是同源跨域

截圖自MDN,連接瀏覽器

 

 

3.同源策略目的:服務器

防止其它網站惡意竊取數據。
例如: 假設沒有同源策略:用戶在銀行網站A上訪問,cookie記錄了A銀行存款金額、存款頻率、存款頻率等信息;當用戶離開A網站,訪問遊戲網站B時,此時網站B能夠讀取cookie。那麼用戶的隱私就被泄露了!
更嚴重的是,cookie每每保存用戶登陸狀態,若是用戶離開A網站(可是沒有退出登陸),那麼B網站實際上是能夠冒充用戶進入A網站websocket

 

4.非同源帶來的結果:

  • cookie,localStorage和indexdDB沒法讀取
  • DOM沒法得到
  • Ajax請求無效(請求發送後,瀏覽器不會進行響應)

 

第二部分:跨域解決方法

1.設置document.domain來跨子域:(適用於cookie、iframe)

好比http://a.test.com和http://b.test.com;

若是設置了document.domain='test.com';那麼二者之間能夠共享cookie(即一級域名相同,二級域名不一樣,能夠設置document.domain來共享cookie)

同時,服務器能夠在設置cookie的時候,指定一級域名,也能達到共享cookie的效果。如:Set-Cookie:key=value;domain=.test.com;path=/

iframe:也能夠經過上述document.cookie設置,從而共享cookie、iframe拿到父窗口的DOM、父窗口拿到iframe的DOM。

如:父窗口是http://a.test.com,iframe是http://test.com;當設置了document.domain="test.com"時,就能進行跨域了。

 

2.同源域名下架設代理服務器:JavaScript將請求發送到代理服務器,代理服務器再將結果返回。

如:'/proxy?url=http://www.test.com'

不過這種顯然須要配置額外服務器,開銷變大。

 

3.使用window.name來跨域:

window.name:在不一樣的頁面(甚至不一樣的域名)加載後依然存在(若是值沒被修改,則不會發生變化),而且name值可達2MB(對於通常的運用徹底夠用)

 

4.片斷識別符(fragment identifier)URL中#後面的部分。好比http://www.test.com#apple的#apple就是片斷識別符。

改變片斷識別符,頁面不會從新刷新

父窗口將信息,寫入子窗口片斷識別符;子窗口經過監聽hashchange事件獲得通知

 

5.window.postMessage:HTML5爲了解決跨域問題,引進的全新API:跨文檔通訊API(cross-document messaging)

父窗口:http://a.com,子窗口:http://b.com;顯然二者不一樣源,可是經過postMessage二者能夠實現跨域通訊

 1 var a=window.open('http://b.com');
 2         //父窗口向子窗口發送信息hello 1
 3         a.postMessage('hello 1','http://b.com');
 4         //子窗口向父窗口發送信息hello 2
 5         window.opener.postMessage('hello 2','http://a.com');
 6 
 7         //父窗口和子窗口都能經過message事件,監聽對方信息
 8         window.addEventListener('message',function(e){
 9             console.log(e.data);
10         })

 

6.JSONP:這個就很常見了。老式瀏覽器都支持,兼容性好,簡單實用。(不過只支持get請求)

基本思想:網頁經過添加一個<script>元素,向服務器發送JSON數據,這種方法是不受同源策略限制的;服務器收到請求後,將數據放入指定的回調函數中返回。

截圖至阮一峯JavaScript標準參考教程。

添加<script>元素,向服務器發送請求,同時請求中指明瞭回調函數foo,服務器以回調函數的形式返回數據。

 

7.websocket:這個是通訊協議,比如是打電話。與傳統的http協議,只能客戶端向服務器發送請求,服務器進行效應的原理不一樣。

websocket能夠由客戶端向服務器發送鏈接請求,也能夠服務器向客戶端發送鏈接請求。它們之間的鏈接是持續打開的數據通道,就比如是打電話!

websocket不受同源策略制約,能夠用來跨域通訊。將能夠通訊的域名放在白名單裏。

 

8.安裝flash插件,如今flash插件用的愈來愈少,並且複雜。不推薦!

 

9.CORS(跨域資源共享)cross-origin resource sharing支持全部類型的請求,對比JSONP只支持get請求

它是一個W3C標準,容許瀏覽器跨域發送XMLHttpResuest對象。這是Ajax跨域的終極解決方法。

目前,IE10以上,現代瀏覽器均支持CORS。

主要原理:瀏覽器發現Ajax跨域請求,就會自動添加一些頭部信息;對於非簡單請求,還會多出一次附加請求;可是這些用戶都察覺不到。而服務器端佈置了CORS接口(設置了相關數據信息如:Access-Control-Allow-Origin)

因此:CORS須要客戶端與服務器同時支持!

更多詳細參考:阮一峯JavaScript標準參考教程

 

10.可參見:PHP Ajax 跨域問題最佳解決方案

經過設置Access-Control-Allow-Origin來實現跨域。

 

更多參考:1.阮一峯JavaScript標準參考教程

2.Ajax廖雪峯的官方網站

3.js中幾種常見的跨域方法原理詳解

相關文章
相關標籤/搜索