瀏覽器出于安全方面的考慮卑吭,只允許與本域下的接口交互芽淡。不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方的資源陨簇。
但在實際運用中我們往往需要獲取不同源的數(shù)據(jù)吐绵,以下為解決跨域問題獲取不同源數(shù)據(jù)的幾種方法
1. JSONP
一個網(wǎng)頁可以從任何網(wǎng)頁獲得js文件迹淌,基于動態(tài)<script>標簽,通過src屬性設置跨域url,可以獲得其他域的資源
JSONP是被包含在函數(shù)中的JSON己单,瀏覽器將JSONP作為JS解析(調用一個函數(shù))唉窃,跨域請求到的JSON作為回調函數(shù)的參數(shù),形如:
callback({"name":"Jim"});
JSONP有兩部分組成纹笼,回調函數(shù)和數(shù)據(jù)纹份。回調函數(shù)是當響應到來時應該在頁面中調用的函數(shù)廷痘,回調函數(shù)的名字一般在請求中指定蔓涧;數(shù)據(jù)就是傳入回調函數(shù)中的JSON數(shù)據(jù)
<script>
var load=document.querySelector('#load');
var shownews=document.querySelector('showNews);
load.addEventListener('click',function(){
var script=document.createElement("script");
script.src='http://a.song.com:8080/getSong?callback=getSong';//設置跨域url,回調函數(shù)名getSong
document.head.appendChild(script);
document.head.removeChild(script);//獲取資源后動態(tài)<script>標簽作用結束笋额,可刪除此節(jié)
});
function getSong(json){//定義回調函數(shù)
console.log(json);
}
</script>
2. CORS
跨域資源共享元暴,允許瀏覽器向跨源服務器,發(fā)出XMLHttpRequest請求兄猩,從而克服了AJAX只能同源使用的限制茉盏。
額外添加一個origin頭部,其中包含了請求頁面的源消息(協(xié)議枢冤、域名和端口)鸠姨,根據(jù)這個頭部信息服務器來決定是否給予響應,例如:
-
request的當前域
- request發(fā)起請求
xhr.open('get', 'http://a.song.com:8080/getSong', true);
- 服務器設置允許請求的域
res.header("Access-Control-Allow-Origin", "http://localhost:8080");
-
頭部信息匹配淹真,跨域請求成功
3.postMessage
當前url:http://a.jrg.com:8080
<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>
向其他域發(fā)送數(shù)據(jù)
<script>
//URL: http://a.jrg.com:8080/a.html
$('.main input').addEventListener('input', function(){
console.log(this.value);
window.frames[0].postMessage(this.value,'*');//發(fā)送數(shù)據(jù)讶迁,*表示任何域,也可精確到某個特定域名
})
當前域http://localhost:8080核蘸,接收來自http://a.jrg.com:8080域發(fā)送的消息
<script>
window.addEventListener('message',function(e) {//監(jiān)聽其他域發(fā)送過來的消息
$('.main input').value = e.data
console.log(e.data);
});
</script>
4.降域
當前頁面的url:
URL: http://a.jrg.com:8080/a.html
向其他域請求資源:
URL: http://b.jrg.com:8080/b.html
降域實現(xiàn)
<script>
//URL: http://a.jrg.com:8080/a.html
document.domain = "jrg.com"
</script>
<script>
//URL: http://b.jrg.com:8080/a.html
document.domain = "jrg.com"
</script>