什么是同源策略
瀏覽器出于安全方面的考慮,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方的資源。
本域指的是?
- 同協議:如都是http或者https
- 同域名:如都是http://jirengu.com/a 和http://jirengu.com/b
- 同端口:如都是80端口
什么是跨域?跨域有幾種實現形式
- 跨域是指 不同域名之間相互訪問 ,只要協議、域名、端口有任何一個不同,都被當作是不同的域
- jsonp
- 降域
- cors
- postMessage
JSONP 的原理是什么
- html中script標簽可以引入其他域下的js,比如引入線上的jquery庫。利用這個特性,可實現跨域訪問接口。需要后端支持
- 定義數據處理函數_fun
- 創建script標簽,src的地址執行后端接口,最后加個參數callback=_fun
- 服務端在收到請求后,解析參數,計算返還數據,輸出 fun(data) 字符串。
- fun(data)會放到script標簽做為js執行。此時會調用fun函數,將data做為參數。
CORS是什么
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請求資源的方式,支持現代瀏覽器,IE支持10以上。 實現方式很簡單,當你使用 XMLHttpRequest 發送請求時,瀏覽器發現該請求不符合同源策略,會給該請求加一個請求頭:Origin,后臺進行一系列處理,如果確定接受請求則在返回結果中加入一個響應頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應頭中是否包含 Origin 的值,如果有則瀏覽器會處理響應,我們就可以拿到響應數據,如果不包含瀏覽器直接駁回,這時我們無法拿到響應數據。所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區別,代碼完全一樣。
跨域的解決方式
// JSONP方式
// 頁面請求
btn.addEventListener('click', function(){
var script = document.createElement('script');
script.src = 'http://xxxx/getData?callback=appendChild'
window.head.appendChild(script);
window.head.removeChild(script);
})
function appendChild(data) {
//JS對數據的操作
}
// 后端數據操作
router.get('/getData', function(req, res) {
var data = [];
//一系列數據操作
var cb = req.query.callback // 獲取callback
if (cb) {
res.send(cb + '(' + JSON.stringify(data) + ')');
}
res.send(data)
})
// CORS方式
// 頁面上還是正常的數據請求,在返回數據的時候設置可以獲取數據的域 代表所有
res.header('Access-Control-Allow-Origin', '');
- JSONP只能實現GET請求,而CORS支持所有類型的HTTP請求。
- 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得數據,比起JSONP有更好的錯誤處理。
- JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS)。
// 降域方式
// 修改document.domain的方法只適用于不同子域
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//設置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 對象
}
</script>
// 子窗口
<script type="text/javascript">
document.domain = 'example.com';//在iframe載入這個頁面也設置document.domain,使之與主頁面的document.domain相同
</script>
window.postMessage(message,targetOrigin) 方法是html5新引進的特性,可以使用它來向其它的window對象發送消息,無論這個window對象是屬于同源或不同源,目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經支持window.postMessage方法。