1: 什么是同源策略
同源策略(Same origin policy)是一種約定,是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響慕的。
現(xiàn)在所有支持JavaScript 的瀏覽器都會使用這個策略。
所謂同源是指挤渔,域名肮街,協(xié)議,端口相同判导。
當一個瀏覽器的兩個tab頁中分別打開來** 百度和谷歌**的頁面
當瀏覽器的百度tab頁執(zhí)行一個腳本的時候會檢查這個腳本是屬于哪個頁面的嫉父,
即檢查是否同源,只有和百度同源的腳本才會被執(zhí)行骡楼。
如果非同源熔号,那么在請求數(shù)據(jù)時,瀏覽器會在控制臺中報一個異常鸟整,提示拒絕訪問引镊。
2: 什么是跨域?跨域有幾種實現(xiàn)形式
跨域:簡單來說就是不同域名之間相互訪問(<em>跨域并非瀏覽器限制了發(fā)起跨站請求篮条,而是跨站請求可以正常發(fā)起弟头,但返回結(jié)果被瀏覽器攔截了</em>)
限制跨域是瀏覽器的行為,不是JS的行為
幾種實現(xiàn)形式
- JSONP(JSON with Padding 填充式JSON 或參數(shù)式JSON)
- CORS(Cross-Origin Resource Sharing涉茧,跨源資源共享)
- HTML5的window.postMessage
window.postMessage(message,targetOrigin) 方法是html5新引進的特性赴恨,可以使用它來向其它的window對象發(fā)送消息,無論這個window對象是屬于同源或不同源伴栓,目前IE8+伦连、FireFox雨饺、Chrome、Opera等瀏覽器都已經(jīng)支持window.postMessage方法惑淳。
window.postMessage允許兩個窗口/幀之間跨域發(fā)送數(shù)據(jù)消息额港。從本質(zhì)上講,window.postMessage是一個跨域的無服務(wù)器墊片的Ajax歧焦。 - 降域
3: JSONP 的原理是什么
在js中移斩,我們雖然不能直接用XMLHttpRequest請求不同域上的數(shù)據(jù),但是在頁面上引入不同域上的js腳本文件卻是可以的绢馍,jsonp正是利用這個特性來實現(xiàn)的向瓷。例如:
<script type="text/javascript">
function dosomething(jsondata){
//處理獲得的json數(shù)據(jù)
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
js文件載入成功后會執(zhí)行我們在url參數(shù)中指定的函數(shù),并且會把我們需要的json數(shù)據(jù)作為參數(shù)傳入舰涌。所以jsonp是需要服務(wù)器端的頁面進行相應(yīng)的配合的猖任。
JSONP實際上就是被包含在一個回調(diào)函數(shù)中的JSON。由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)舵稠〕回調(diào)函數(shù)是當響應(yīng)到來時應(yīng)該在頁面中調(diào)用的函數(shù)入宦,而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的JSON數(shù)據(jù)哺徊。
JSONP的優(yōu)點是:
- 它不像XMLHttpRequest對象實現(xiàn)的Ajax請求那樣受到同源策略的限制;
- 它的兼容性更好乾闰,在老版本的瀏覽器中可以運行落追,不需要XMLHttpRequest或ActiveX的支持;
- 它在請求完畢后可以通過調(diào)用callback的方式回傳結(jié)果涯肩,方便調(diào)用轿钠。
JSONP的缺點則是: - 它只支持GET請求而不支持POST等其它類型的HTTP請求,不能提交大量數(shù)據(jù)病苗;
- 它只支持跨域HTTP請求這種情況疗垛,不能解決不同域的兩個頁面之間如何進行JavaScript調(diào)用的問題。
4: CORS是什么硫朦?
1.CORS(Cross-Origin Resource Sharing贷腕,跨源資源共享)是W3C 的一個工作草案,定義了在必須訪問跨源資源時咬展,瀏覽器與服務(wù)器應(yīng)該如何溝通泽裳。CORS 背后的基本思想,就是使用自定義的HTTP 頭部讓瀏覽器與服務(wù)器進行溝通破婆,從而決定請求或響應(yīng)是應(yīng)該成功涮总,還是應(yīng)該失敗。
2.實現(xiàn)此功能非常簡單祷舀,只需由服務(wù)器發(fā)送一個響應(yīng)標頭即可瀑梗。
瀏覽器支持情況:
- IE 8+
- Firefox 3.5+
- Opera 12+
- Safari 4+
- Chrome 3+
假設(shè)我們頁面或者應(yīng)用已在 http://www.a.com/ 上了烹笔,而我們打算從 http://www.b.com 請求提取數(shù)據(jù)。一般情況下抛丽,如果我們直接使用 AJAX 來請求將會失敗箕宙,瀏覽器也會返回錯誤。利用 CORS铺纽,http://www.b.com 只需添加一個標頭柬帕,就可以允許來自 http://www.a.com 的請求。下面是用php進行的設(shè)置:
//服務(wù)器需要聲明這么一條響應(yīng)頭狡门,即可輕松跨域
//PHP中的 header() 設(shè)置陷寝,“*”號表示允許任何域向我們的服務(wù)端提交請求:
header("Access-Control-Allow-Origin: *")
//也可以設(shè)置指定的域名,如域名 http://h5.jd.com 其馏,那么就允許來自這個域名的請求:
header("Access-Control-Allow-Origin: http://example.com")
CORS和JSONP對比:
CORS與JSONP相比凤跑,更為先進、方便和可靠叛复。
1仔引、 JSONP只能實現(xiàn)GET請求,而CORS支持所有類型的HTTP請求褐奥。
2咖耘、 使用CORS,開發(fā)者可以使用普通的XMLHttpRequest發(fā)起請求和獲得數(shù)據(jù)撬码,比起JSONP有更好的錯誤處理儿倒。
3、 JSONP主要被老的瀏覽器支持呜笑,它們往往不支持CORS夫否,而絕大多數(shù)現(xiàn)代瀏覽器都已經(jīng)支持了CORS)。
5: 根據(jù)視頻里的講解演示三種以上跨域的解決方式
josnp
function addScriptTag(src) {
var script = document.createElement('script');
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
//
foo({
"ip": "8.8.8.8"
});
降域
//在頁面 http://www.example.com/a.html 中設(shè)置document.domain:
<iframe src="example.com/b.html" id="iframe" onload="test()"></iframe>
<script>
document.domain='example.com';//設(shè)置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);
}
</script>
//在頁面 http://example.com/b.html中也設(shè)置document.domain
<script>
document.domain='example.com';//在iframe載入的這個頁面也設(shè)置 document.domain與主頁面相同
</script>
//而且是必須的叫胁,雖然這個文檔的domain就是example.com,但是還是必須顯示的設(shè)置document.domain的值
跨域資源共享(CORS)
這種方式只要服務(wù)端把response的header頭中設(shè)置Access-Control-Allow-Origin為制定可請求當前域名下數(shù)據(jù)的域名即可
//相關(guān)Ajax代碼可能如下
var xhr = new XMLHttpRequest();
xhr.open("GET", "'http://www.baidu.com'", true);
//區(qū)別就在于相對路徑換成了其他域的絕對路徑凰慈,也就是你要跨域訪問的接口地址。
xhr.send();
//服務(wù)器端
res.header('Access-Control-Allow-Origin','*');//“*”號表示允許任何域向我們的服務(wù)端提交請求
res.header('Access-Control-Allow-Origin','http://www.baidu.com')//也可以設(shè)置指定的域名