同源策略
1越驻、什么是源
以下面這段代碼為例
|http://www.iconfont.cn:80/home/index?spm=a313x.7781069.1998910419.2
-
http://
是協(xié)議名 -
www.iconfont.cn
是域名 -
80
是端口號叽掘,默認情況下不顯示楣铁,https協(xié)議下默認端口號是43,ftp協(xié)議下默認端口號是21 -
/home/index
是帶層次的文件路徑 -
spm=a313x.7781069.1998910419.2
是查詢字符段 - 源(origin)就是指協(xié)議更扁、域名盖腕、端口號
2、什么是同源
- 即地址里的協(xié)議浓镜、域名和端口號都相同溃列,則屬于同源
以http://abc.efg.com/h/index.html
為例做同源檢測有下表
url | 結果 | 原因 |
---|---|---|
http://abc.efg.com/h/demo.html |
成功 | |
http://abc.efg.com/j/index.html |
成功 | |
https://abc.efg.com/h/index.html |
失敗 | 協(xié)議不相同 |
http://abc.efg.cn/h/index.html |
失敗 | 域名不相同 |
http://abc.efg.com:8080/h/index.html |
失敗 | 端口不相同 |
什么是同源策略
同源策略是一種約定,是瀏覽器最核心也是最基本的安全功能膛薛,主要體現(xiàn)在同源策略會限制來自不同源的文檔和腳本對當前源的文檔數(shù)據(jù)的讀取或設置某些屬性听隐,是用于隔離潛在惡意文件的重要安全機制
同源策略控制了不同源的交互,主要有三類交互
- 跨域寫:通常允許哄啄,比如鏈接雅任、重定向和表單提交(因為表單提交不需要反饋數(shù)據(jù))
- 跨域資源嵌入:通常允許,下面會給出跨域資源嵌入的例子
- 跨域讀:通常不允許咨跌,比如在使用
XMLHttpRequest
的時候會發(fā)生跨域問題沪么,不過通過某些方法仍可以進行跨域讀
注意:IE是例外
在同源策略中,Internet Explorer有兩點不同
- 授信范圍(Trust Zones):兩個相互之間高度互信的域名锌半,如公司域名 (corporate domains)禽车,不遵守同源策略的限制。
- 端口:未將端口號加入到同源策略的組成部分之中,因此
http://abc.com:81/index.html
和http://abc.com/index.html
屬于同源并且不受任何限制殉摔。
跨域
瀏覽器同源策略的機制的存在無法避免州胳,而我們實際應用中又不可避免的對于不同域要操作,那我們就只能跨域了
如何跨域
- 降域 document.domain
http://a.bcd.com/index.html
http://b.bcd.com/index.html
上面兩個url雖然有個共同的bcd.com
的一級域名逸月,二級域名卻不一樣陋葡,這樣的話同源策略也一樣不認為它倆是同源,對于這種情況彻采,我們可以將兩個頁面都設置document.domain='bcd.com'
腐缤,這樣的話兩個頁面都可以互相訪問
-
這個方式的特點
- 只能在父域名與子域名之間使用,且將 域名設置為
bcd.com
后肛响,不能再設置為原先的域名岭粤。 - 存在安全性問題,當一個站點被攻擊后特笋,另一個站點會引起安全漏洞剃浇。
- 這種方法只適用于 Cookie 和 iframe 窗口。
- 只能在父域名與子域名之間使用,且將 域名設置為
JSONP跨域
JSONP和JSON并沒什么關系
我們要知道一個概念即<script>
里的src
屬性是不受同源策略的影響的猎物,JSONP的原理就是利用這個機制來進行跨域虎囚,
JSONP的原理:(舉例:a.com/jsonp.html
想得到b.com/main.js
中的數(shù)據(jù))在a.com
的jsonp.html里創(chuàng)建一個回調(diào)函數(shù)xxx,動態(tài)添加<script>元素蔫磨,向服務器發(fā)送請求淘讥,請求地址后面加上查詢字符串,通過callback參數(shù)指定回調(diào)函數(shù)的名字堤如。請求地址為http://b.com/main.js?callback=xxx
蒲列。在main.js中調(diào)用這個回調(diào)函數(shù)xxx,并且以JSON數(shù)據(jù)形式作為參數(shù)傳遞搀罢,完成回調(diào)蝗岖。我們來看看代碼:
// a.com/jsonp.html中的代碼
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://b.com/main.js?callback=foo');
} //window.onload是為了讓頁面加載完成后再執(zhí)行
function foo(data) {
console.log(data.name+"歡迎您");
};
//b.com/main.js中的代碼
foo({name:"hl"})
JSONP跨域也有些問題存在
- 使用這種方法,只要是個網(wǎng)站都可以拿到b.com里的數(shù)據(jù)榔至,存在安全性問題抵赢。需要網(wǎng)站雙方商議基礎token的身份驗證。
- 只能是GET唧取,不能POST铅鲤。
- 可能被注入惡意代碼,篡改頁面內(nèi)容兵怯,可以采用字符串過濾來規(guī)避此問題彩匕。
-
CORS
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)媒区,是一種ajax跨域 請求資源的方式驼仪,支持現(xiàn)代瀏覽器掸犬,支持IE10以上。實現(xiàn)的方式很簡單绪爸,當你使用XMLHttpRequest發(fā)送請求時湾碎,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個請求頭:Origin奠货,后臺進行一系列處理介褥,如果確定接受請求則在返回的結果中加入一個響應頭:Access-Control-Allow-Origin;瀏覽器判斷響應頭中是否包含Origin的值,如果有則瀏覽器會處理響應递惋,我們就可以拿到響應數(shù)據(jù)柔滔,如果不包含瀏覽器直接駁回,這時我們無法拿到響應數(shù)據(jù)萍虽。所以睛廊,CORS的表象是讓你覺得他與同源的AJAX的請求沒啥區(qū)別,代碼完全一樣杉编。
在剛才的例子中超全,在b.com
里面添加響應頭聲明允許a.com
的訪問,代碼如下
Access-Control-Allow-Origin: http://a.com
這樣a.com
就可以訪問b.com
里面的數(shù)據(jù)了
注意:此方法IE8以下完全不支持邓馒,IE8以上部分支持嘶朱,具體參照caniuse
CORS詳細內(nèi)容請移步至阮老師-CORS詳解
-
其它方式
- HTML5的postMessage方法
- window.name
- location.hash