題目1: 什么是同源策略?
瀏覽器出于安全方面的考慮,只允許與本域下的接口交互。不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方的資源。
http://a.jrg.com:8080/
1.http: 指協(xié)議,其他協(xié)議有https\file\ftp\ssh\mailto\tel等
2.a.jrg.com: 指域名
3.8080: 指端口,默認端口號為80,若為80一般就不寫出來了
只要協(xié)議、域名、端口有任何一個不同,都會被當作是不同的域。
同源舉例:
http://jrg.com/a/b.js 和 http://jrg.com/index.php
不同源舉例:
http://me.com/main.js 和 https://me.com/a.php (協(xié)議不同)
http://a.me.com/main.js 和 http://b.me.com/a.php (域名不同,域名必須完全相同才可以)
http://me.com/main.js 和 http://me.com:8080/a.php (端口不同,第一個是80)
需要注意: 對于當前頁面來說頁面存放的 JS 文件的域不重要,重要的是加載該 JS 頁面所在什么域
題目2: 什么是跨域?跨域有幾種實現(xiàn)形式?
跨域就是突破同源策略的限制,去不同的域下訪問數(shù)據(jù)
- JSONP (實際就是以加載js的方式,執(zhí)行拿到不同域名中的數(shù)據(jù))
-
CORS (在后端的返回頭部設置
Access-Control-Allow-Origin
添加允許訪問的域名) -
降域 (2者都設置
document.domain=" "
訪問的前后都要降域并且2者都要有同一個基礎域名,比如a.jrg.com
和b.jrg.com
,降域后都為jrg.com
) - postMessage 在兩個窗口/frames間發(fā)送數(shù)據(jù)信息,但不是瀏覽器跟服務器之間交互,而是在兩個客戶端之間通信
題目3: JSONP 的原理是什么?
由于同源策略,XMLHttpRequest()
對象無法跨域,但<script>
、<img>
、<link>
等標簽是可以跨域的。所以可以利用<script>標簽來向服務器發(fā)送請求。
- 通過script標簽引入一個js文件,在src中傳遞一個
callback=function
參數(shù)給服務端 - 服務端返回數(shù)據(jù)時會將這個callback參數(shù)作為函數(shù)名包裹住JSON數(shù)據(jù)
function([json數(shù)據(jù)])
- 當這個js文件載入成功后就會執(zhí)行我們指定的function回調函數(shù),并且會把我們需要的JSON數(shù)據(jù)作為參數(shù)傳入
題目4: CORS是什么?參考
跨域資源共享(Cross-origin resource sharing),是一種ajax跨域請求資源的方式(支持現(xiàn)代瀏覽器,IE支持10以上)。
實現(xiàn)方式:當使用 XMLHttpRequest
發(fā)送請求時,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個請求頭:Origin
,后臺進行一系列處理,如果確定接受請求則在返回結果中加入一個響應頭:Access-Control-Allow-Origin
; 瀏覽器判斷該相應頭中是否包含 Origin
的值,如果有則瀏覽器會處理響應,我們就可以拿到響應數(shù)據(jù),如果不包含瀏覽器直接駁回,這時我們無法拿到響應數(shù)據(jù)。
所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區(qū)別,代碼完全一樣。
比如發(fā)送了一個origin頭部:
Origin: http://a.jrg.com:8080
如果服務器(后端)認為這個請求可以接受,就在Access-Control-Allow-Origin頭部中發(fā)回相同的源信息:
Access-Control-Allow-Origin: http://a.jrg.com:8080
(與請求相同)
題目5: 根據(jù)視頻里的講解演示三種以上跨域的解決方式
cors
在服務端發(fā)送數(shù)據(jù)之前添加一個響應頭,允許該域名跨域獲取數(shù)據(jù)
降域
當a.jrg.com 想要操作 b.jrg.com的文件,可以通過兩者都添加document.domain = "jrg.com"
降域為jrg.com才能互相操作
缺點:只能用于相同的父級域名
PostMessage
postMessage的原理是會向另一個地方發(fā)送信息,另一個地方通常是iframe或者是由當前頁面彈出的窗口。
當父級頁面里包含了不同域里的iframe,可以通過這種方式來進行通信
當父級頁面可以通過postMessgae將內容發(fā)送給子iframe。可以通過監(jiān)聽message事件,來獲取信息。
window.frames[0].postMessage(value,'*')
window.addEventListener('message',function(e) {
console.log(e.data);
});
iframe可以通過postMessgae將內容發(fā)送給父頁面??梢酝ㄟ^監(jiān)聽message事件,來獲取信息。
window.parent.postMessage(value,'*')
window.addEventListener('message',function(e) {
console.log(e.data);
});