什么是同源策略脑沿?
同源策略 是由Netscape提出的一個著名的安全策略泪酱,現(xiàn)在所有支持JavaScript 的瀏覽器都會使用這個策略衔蹲。這種策略只是一個規(guī)范,并不是強(qiáng)制要求芭逝,各大廠商的瀏覽器只是針對同源策略的一種實(shí)現(xiàn)塌碌。它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略旬盯,則瀏覽器的正常功能可能都會受到影響誊爹。
同源是指:
同協(xié)議:都是http或者h(yuǎn)ttps
同端口:都是80端口
為什么要有同源限制蹬刷?
如果沒有同源策略黑客很容易竊取密碼與用戶信息。
瀏覽器出于安全方面的考慮频丘,只允許與本域下的接口交互办成。不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對方的資源搂漠。
什么是跨域迂卢?
跨域是指從一個域名的網(wǎng)頁去請求另一個域名的資源。比如從www.baidu.com 頁面去請求 www.google.com 的資源桐汤。
跨域的嚴(yán)格一點(diǎn)的定義是:只要 協(xié)議而克,域名,端口有任何一個的不同怔毛,就被當(dāng)作是跨域员萍。
同源:
http://jirengu.com/a/b.js 和 http://jirengu.com/index.php
不同源:
http://jirengu.com/main.js 和 https://jirengu.com/a.php (協(xié)議不同)
http://jirengu.com/main.js 和 http://bbs.jirengu.com/a.php (域名不同,域名必須完全相同才可以)
http://jiengu.com/main.js 和 http://jirengu.com:8080/a.php (端口不同,第一個是80)
c.png
注意: 對于當(dāng)前頁面來說頁面存放的 JS 文件的域不重要拣度,重要的是加載該 JS 頁面所在什么域
跨域的幾種實(shí)現(xiàn)方法:
- jsonp
- CORS:跨域資源共享(Cross-Origin Resource Sharing)
- 降域
- postMessage()
JSONP原理
利用<script>標(biāo)簽沒有跨域限制來達(dá)到與第三方通訊的目的碎绎。當(dāng)需要通訊時,本站腳本創(chuàng)建一個<script>元素抗果,地址指向第三方的API網(wǎng)址筋帖,形如:
<script src="http://www.example.net/api?param1=1¶m2=2"></script>
并提供一個回調(diào)函數(shù)來接收數(shù)據(jù)(函數(shù)名可約定,或通過地址參數(shù)傳遞)冤馏。
第三方產(chǎn)生的響應(yīng)為json數(shù)據(jù)的包裝(故稱之為jsonp日麸,即json padding),形如:
callback({"name":"hax","gender":"Male"})
這樣瀏覽器會調(diào)用callback函數(shù)逮光,并傳遞解析后json對象作為參數(shù)代箭。本站腳本可在callback函數(shù)里處理所傳入的數(shù)據(jù)。
CORS是什么涕刚?
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing)梢卸,是一種 ajax 跨域請求資源的方式。
IE支持10以上副女。當(dāng)你使用 XMLHttpRequest 發(fā)送請求時蛤高,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個請求頭:Origin碑幅,后臺進(jìn)行一系列處理戴陡,如果確定接受請求則在返回結(jié)果中加入一個響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值,如果有則瀏覽器會處理響應(yīng)沟涨,我們就可以拿到響應(yīng)數(shù)據(jù)恤批,如果不包含瀏覽器直接駁回,這時我們無法拿到響應(yīng)數(shù)據(jù)裹赴。
例如:
在后臺設(shè)置響應(yīng)頭喜庞,同意http://a.com:8080源來請求數(shù)據(jù)
res.setHeader('Access-Control-Allow-Origin','http://a.com:8080')
a.com的請求頭會帶上自己的源
Origin: http://a.com:8080
如果匹配則可以共享資源
降域
當(dāng)兩個頁面不同域诀浪,但是它們的父域之上都相同(端口),那么可以使用降域的方法來實(shí)現(xiàn)跨域延都。
對于主域相同而子域不同的情況下雷猪,可以通過設(shè)置 document.domain 的辦法來解決。
document.domain = "jrg.com"
兩個頁面的域名后綴都要添加http://jrg.com晰房,把兩個網(wǎng)頁都降到同一個組域下求摇,這樣就可以訪問了。
postMessage
window.postMessage() 方法可以安全地實(shí)現(xiàn)跨源通信殊者。通常与境,對于兩個不同頁面的腳本,只有當(dāng)執(zhí)行它們的頁面位于具有相同的協(xié)議(通常為https)猖吴,端口號(443為https的默認(rèn)值)摔刁,以及主機(jī) (兩個頁面的模數(shù) Document.domain設(shè)置為相同的值) 時,這兩個腳本才能相互通信海蔽。
需要在全局的代碼中添加
window.frames[0].postMessage(this.value,'*');
而在需要訪問數(shù)據(jù)的網(wǎng)頁中用來監(jiān)聽postMessage
例如:
創(chuàng)建a.html
<div class="ct">
<h1>使用postMessage實(shí)現(xiàn)跨域</h1>
<div class="main">
<input type="text" placeholder="http://a.jrg.com:8080/a.html">
</div>
<iframe src="http://localhost:8080/b.html" frameborder="0" ></iframe>
</div>
<script>
//URL: http://a.jrg.com:8080/a.html
$('.main input').addEventListener('input', function(){
console.log(this.value);
window.frames[0].postMessage(this.value,'*'); //* ,任何域下都可接受請求
})
window.addEventListener('message',function(e) {
$('.main input').value = e.data
console.log(e.data);
});
function $(id){
return document.querySelector(id);
}
</script>
創(chuàng)建b.html
<input id="input" type="text" placeholder="http://b.jrg.com:8080/b.html">
<script>
// URL: http://b.jrg.com:8080/b.html
$('#input').addEventListener('input', function(){
window.parent.postMessage(this.value, '*');
})
window.addEventListener('message',function(e) {
$('#input').value = e.data
console.log(e.data);
});
function $(id){
return document.querySelector(id);
}
</script>
以上是我對跨域的理解共屈,有不足之處請多見諒