1:什么是同源策略
- 瀏覽器出于安全及用戶隱私方面的考慮,只允許腳本與本域下的接口交互。不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方的資源。(不允許域名不同的網站之間互相調用ajax,別的比如js、css還是可以訪問)
- 同源策略分以下兩種:
- DOM同源策略:禁止對不同源頁面DOM進行操作。這里主要場景是iframe跨域的情況,不同域名的iframe是限制互相訪問的。
- XmlHttpRequest同源策略:禁止使用XHR對象向不同源的服務器地址發起HTTP請求。
- 本域指的是?
- 同協議:如都是http或者https
- 同域名:如都是http://jirengu.com/a 和http://jirengu.com/b
- 同端口:如都是80端口
http://www.zhihu.com vs http://zhihu.com 不同源(域名必須完全相同才可以)
需要注意的是:對于當前頁面來說,存放js的頁面的域不重要,重要的是加載(執行)該js的頁面是什么域
同源策略是瀏覽器自身的安全機制,出現跨域時,請求是發到服務器的,服務器也給了響應,但是瀏覽器覺得數據不安全所以進行了攔截
2:什么是跨域?跨域有幾種實現形式
- 瀏覽器禁止訪問的場景:
- js里發送ajax請求,如果請求的url和當前頁面的url非同域,則瀏覽器會拒絕提供數據并報錯
- 當前頁面下引入iframe,如果iframe里的頁面和當前頁面的url非同域,則瀏覽器會禁止當前頁面的js獲取或者操作iframe下頁面的dom
- 對于場景1,可以通過jsonp或者cors繞過瀏覽器的限制
- 對于場景2,如果兩個頁面擁有相同的一級域名(如 a.hunger.com 和b.hunger.com)可通過降域的方式,如果是不同域名,可使用postmessage)
3:JSONP 的原理是什么
HTML 中 script 標簽可以加載其他域下的js,比如我們經常引入一個其他域下線上cdn的jQuery。那如何利用這個特性實現從其他域下獲取數據呢?
可以先這樣試試:
<script src="http://api.jirengu.com/weather.php"></script>
這時候會向天氣接口發送請求獲取數據,獲取數據后做為 js 來執行。 但這里有個問題, 數據是 JSON 格式的數據,直接作為 JS 運行的話我如何去得到這個數據來操作呢?
這樣試試:
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
這個請求到達后端后,后端會去解析callback這個參數獲取到字符串showData,在發送數據做如下處理:
之前后端返回數據: {"city": "hangzhou", "weather": "晴天"}
現在后端返回數據: showData({"city": "hangzhou", "weather": "晴天"})
, 前端script標簽在加載數據后會把 「showData({“city”: “hangzhou”, “weather”: “晴天”})」做為 js 來執行,這實際上就是調用showData這個函數,同時參數是 {“city”: “hangzhou”, “weather”: “晴天”}。 用戶只需要在加載提前在頁面定義好showData這個全局函數,在函數內部處理參數即可。
<script>
function showData(ret){
console.log(ret);
}
</script>
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
這就是 JSONP(JSON with padding)
總結:JSONP是通過 script 標簽加載數據的方式去獲取數據當做 JS 代碼來執行,提前在頁面上聲明一個函數,函數名通過接口傳參的方式傳給后臺,后臺解析到函數名后在原始數據上「包裹」這個函數名,發送給前端。換句話說,JSONP 需要對應接口的后端的配合才能實現。
4:CORS是什么
- CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請求資源的方式,支持現代瀏覽器,IE支持10以上。 實現方式很簡單,當你使用 XMLHttpRequest 發送請求時,瀏覽器發現該請求不符合同源策略,會給該請求加一個請求頭:Origin,后臺進行一系列處理,如果確定接受請求則在返回結果中加入一個響應頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應頭中是否包含 Origin 的值,如果有則瀏覽器會處理響應,我們就可以拿到響應數據,如果不包含瀏覽器直接駁回,這時我們無法拿到響應數據。所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區別,代碼完全一樣。
CORS的本質就是在后臺加了一條說明,說明哪些域可以訪問該接口。瀏覽器在收到響應以后會對照響應頭里面的
Access-Control-Allow-Origin
的值,如果當前頁面的域符合該值要求,那就可以處理數據。如果不符,那么就拒絕響應數據。