同源策略是由Netscape提出的著名安全策略,是瀏覽器最核心曼追、基本的安全功能,它限制了一個(gè)源(origin)中加載文本或者腳本與來(lái)自其他源(origin)中資源的交互方式舟陆,所謂的同源就是指協(xié)議捞挥、域名滩届、端口相同。當(dāng)瀏覽器執(zhí)行一個(gè)腳本時(shí)會(huì)檢查是否同源差导,只有同源的腳本才會(huì)執(zhí)行试躏,如果不同源即為跨域
跨域的幾種方式
跨域有幾種實(shí)現(xiàn)形式
1,JSONP
最常見(jiàn)的一種跨域方式设褐,其背后原理就是利用了script標(biāo)簽不受同源策略的限制颠蕴,在頁(yè)面中動(dòng)態(tài)插入了script,script標(biāo)簽的src屬性就是后端api接口的地址助析,并且以get的方式將前端回調(diào)處理函數(shù)名稱(chēng)告訴后端犀被,后端在響應(yīng)請(qǐng)求時(shí)會(huì)將回調(diào)返還,并且將數(shù)據(jù)以參數(shù)的形式傳遞回去外冀。
2寡键,CORS
Cross-Origin Resource Sharing(跨域資源共享)是一種允許當(dāng)前域(origin)的資源(比如html/js/web service)被其他域(origin)的腳本請(qǐng)求訪問(wèn)的機(jī)制。當(dāng)使用XMLHttpRequest發(fā)送請(qǐng)求時(shí)雪隧,瀏覽器如果發(fā)現(xiàn)違反了同源策略就會(huì)自動(dòng)加上一個(gè)請(qǐng)求頭:origin,后端在接受到請(qǐng)求后確定響應(yīng)后會(huì)在Response Headers中加入一個(gè)屬性:Access-Control-Allow-Origin,值就是發(fā)起請(qǐng)求的源地址(http://127.0.0.1:8888)西轩,瀏覽器得到響應(yīng)會(huì)進(jìn)行判斷Access-Control-Allow-Origin的值是否和當(dāng)前的地址相同,只有匹配成功后才進(jìn)行響應(yīng)處理膀跌。
3遭商,降域跨域
不同域下iframe的操作,當(dāng)這兩個(gè)域名都屬于同一個(gè)基礎(chǔ)域名!而且所用的協(xié)議捅伤,端口都一致的時(shí)候,可以使用降域來(lái)實(shí)現(xiàn)跨域巫玻。加上document.domin=‘共同的域名’進(jìn)行降域處理
4丛忆,postMessage
在HTML5中新增了postMessage方法祠汇,postMessage可以實(shí)現(xiàn)跨文檔消息傳輸(Cross Document Messaging),Internet Explorer 8, Firefox 3, Opera 9, Chrome 3和 Safari 4都支持postMessage熄诡。該方法可以通過(guò)綁定window的message事件來(lái)監(jiān)聽(tīng)發(fā)送跨文檔消息傳輸內(nèi)容可很。使用postMessage實(shí)現(xiàn)跨域的話原理就類(lèi)似于jsonp,動(dòng)態(tài)插入iframe標(biāo)簽凰浮,再?gòu)膇frame里面拿回?cái)?shù)據(jù)我抠,私認(rèn)為用作跨頁(yè)面通信更加適合
jsonp的原理
ajax請(qǐng)求受同源策略影響,不允許進(jìn)行跨域請(qǐng)求袜茧,而script標(biāo)簽src屬性中的鏈接卻可以訪問(wèn)跨域的js腳本菜拓,利用這個(gè)特性,服務(wù)端不再返回JSON格式的數(shù)據(jù)笛厦,而是返回一段調(diào)用某個(gè)函數(shù)的js代碼纳鼎,在src中進(jìn)行了調(diào)用,這樣實(shí)現(xiàn)了跨域裳凸。
jsonp的例子
<!DOCTYPE html>
<html>
<head>
<title>GoJSONP</title>
</head>
<body> <
script type="text/javascript">
function jsonhandle(data){
alert("age:" + data.age + "name:" + data.name);
}
</script> <script type="text/javascript" src="jquery-1.8.3.min.js">
</script> <script type="text/javascript">
$(document).ready(function(){
var url = "http://www.practice-zhao.com/student.php?id=1&callback=jsonhandle";
var obj = $('<script><\/script>');
obj.attr("src",url);
$("body").append(obj);
});
</script>
</body>
</html>
這里動(dòng)態(tài)的添加了一個(gè)script標(biāo)簽贱鄙,src指向跨域的一個(gè)php腳本,并且將上面的js函數(shù)名作為callback參數(shù)傳入
php代碼
<?php
$data = array( 'age' => 20, 'name' => '張三', );
$callback = $_GET['callback'];
echo $callback."(".json_encode($data).")";
return;
PHP代碼返回了一段JS語(yǔ)句姨谷,即
此時(shí)訪問(wèn)頁(yè)面時(shí)逗宁,動(dòng)態(tài)添加了一個(gè)script標(biāo)簽,src指向PHP腳本梦湘,執(zhí)行返回的JS代碼疙剑,成功彈出提示框。
所以JSONP將訪問(wèn)跨域請(qǐng)求變成了執(zhí)行遠(yuǎn)程JS代碼践叠,服務(wù)端不再返回JSON格式的數(shù)據(jù)言缤,而是返回了一段將JSON數(shù)據(jù)作為傳入?yún)?shù)的函數(shù)執(zhí)行代碼。