3000 字说说跨域!面试官听完之后露出了满意的笑容
??點擊上方?好好學java?,選擇?星標?公眾號
重磅資訊、干貨,第一時間送達 今日推薦:是時候扔掉Postman了,又一個被低估的IDEA插件出來了...個人原創+1博客:點擊前往,查看更多 作者:前端求職中_杭州_感謝內推 鏈接:https://juejin.im/post/5e74e690e51d4526d87c93df同源策略
在說跨域之前,首先需要了解的一個概念就是”同源策略“。
什么是源?
源=協議+域名+端口號。
如果兩個url的協議、域名、端口號完全一致,那么這兩個url就是同源的。
我們可以通過window.origin或location.origin得到當前源。
https://wang.com https://ergou.com //不同源,域名不一致(記住:只有完全一模一樣才算同源)http://wang.com/index.html http://wang.com/server.php //同源localhost 調用 127.0.1 //不同源什么是同源策略?
同源策略即:不同源之間的頁面,不準互相訪問數據。
瀏覽器規定:如果JS運行在源A里,那么就只能獲取源A的數據,不能獲取源B的數據,即不允許跨域。
假設 wang.com/index.html引用了ergou.com/1.js,那么就說1.js運行在源wang.com里
注意,這和ergou.com沒有關系,雖然1.js是從它那里下載的.
所以1.js就只能獲取wang.com的數據,這就是瀏覽器的功能,瀏覽器就是故意這樣設計的。
為什么會有同源策略?
之所以需要使用同源策略,就是為了保護用戶的隱私。
以微信為例,源為 https://user.weixin.com,假設當前用戶已經登錄,并且AJAX請求 /friends.json 可以獲取用戶好友列表。
這個時候黑客來了,他把 https://user-winxin.com分享給你,實際上這是一個釣魚網站,你點開這個網頁,這個網頁也請求你的好友列表 https://user.weixin.com/friends.json。
請問,這個時候你的好友列表是不是就被黑客給偷走了?
問題的根源
之所以會出現這個問題,其根源就在于無法區分發送者。
微信里面的JS和黑客的JS發送到請求幾乎沒有區別(referer區別)
但是如果后臺的開發者沒有檢查 referer,那么就完全沒有區別。
所以,如果沒有同源策略,任何頁面都能偷走微信里面的數據,甚至是支付寶里面的余額。
安全原則
有的小伙伴可能會問,既然referer有區別,那檢查referer不就好了?
安全原則:安全鏈條上的強度取決于安全鏈條上最弱的一環。
同時,萬一這個網站的后端開發者是一個傻叉呢?
所以瀏覽器應該主動預防這種偷數據的行為。
總之,為了保護用戶的隱私,瀏覽器設置了嚴格的同源策略。
如果瀏覽器不限制跨域,一定是這個瀏覽器出現了bug。
跨域
什么是跨域?
跨域,即瀏覽器試圖執行其他網站的腳本。但是由于同源策略的限制,導致我們無法實現跨域。
關于跨域的幾個問題
為什么a.wang.com訪問wang.com也算跨域?
因為歷史上,出現過不同的公司共用域名,a.wang.com和wang.com不一定是同一個網站,瀏覽器謹慎起見,認為這是不同的源。
為什么不同端口也算跨域?
原因同上,一個端口一個公司的情況也不是沒有的。
記住:安全鏈條的強度取決于最弱的一環,所有和安全相關的問題都要謹慎對待。
為什么兩個網站的IP一樣,也算跨域?
原因同上,因為IP也是可以共用的。
為什么可以跨域使用CSS、JS和圖片等?
同源策略限制的是數據訪問,我們引用CSS、JS和圖片的時候,其實并不知道其內容,我們只是在引用。
CORS跨域
什么是CORS?
CORS的全稱是"跨域資源共享"(Cross-origin resource sharing)。 它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
如何理解CORS?
如果wang.com和ergou.com這兩個網站都是我的,我就是想讓wang.com去訪問ergou.com里面的數據應該怎么辦呢?
只需要wang.com在響應頭里寫ergou.com可以訪問即可。這就是CORS。
實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。
兩種請求
CORS跨域分為兩種請求,一種是簡單請求,另外一種就是復雜請求。
簡單請求
只要滿足以下條件的就是簡單請求:
請求方式為HEAD、POST 或者 GET
http頭信息不超出以下字段:Accept、Accept-Language 、 Content-Language、 Last-Event-ID、 Content-Type(限于三個值:application/x-www-form-urlencoded、multipart/form-data、text/plain)
簡單請求的實現具體來說就是在信息頭中加入一個Origin字段:
GET /cors HTTP/1.1 Origin: http://wang.com Host: api.ergou.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0 ...Origin的作用就是用來說明本次請求來自哪個源,服務器會根據Origin的值來判斷是否接受本次請求。
如果Origin所表示的源不被服務器接受,即瀏覽器發現回應的信息頭中沒有Access-Control-Allow-Origin字段,就會自動拋出一個錯誤。
注意:這種錯誤是無法通過狀態碼識別的,這也是通過CORS實現跨域請求的一個弊端。
如果Origin所表示的源被服務器端所接受,那么服務器就會返回如下響應:
Access-Control-Allow-Origin: http://api.ergou.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8Access-Control-Allow-Origin :該字段是必須的。它的值要么是請求時Origin字段的值,要么是一個*,表示接受任意域名的請求
Access-Control-Allow-Credentials: 該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。設為true,即表示服務器明確許可,Cookie可以包含在請求中,一起發給服務器。這個值也只能設為true,如果服務器不要瀏覽器發送Cookie,刪除該字段即可。(注意:如果要發送cookie,不僅要進行上述的設置,還要在AJAX請求中設置withCredentials屬性)
Access-Control-Expose-Headers:該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
復雜請求
所謂復雜請求,即不滿足上述條件的請求就是復雜請求。
比如請求的方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
復雜請求首先會發起一個預檢請求,該請求是 option 方法的,通過該請求來知道服務端是否允許跨域請求。
var url = 'http://api.wang.com/cors'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send();上面的請求就是一個復雜請求,當瀏覽器發現這是一個復雜請求之后,就會主動發出一個預檢請求,詢問服務器是否允許本次請求。
服務器收到預檢請求之后,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認允許跨源請求,才會做出相應的回應。
Access-Control-Allow-Origin: http://api.wang.com Content-Type: text/html; charset=utf-8CORS存在的問題
不支持IE8/9,如果要在IE8/9使用CORS跨域需要使用XDomainRequest對象來支持CORS。
JSONP跨域
什么是JSONP?
我們在跨域的時候由于當前的瀏覽器不支持 CORS 或者因為某些條件不支持 CORS,我們必須使用另外一種方式來跨域,于是我們就請求一個 JS 文件,這個 JS 文件會執行一個回調,回調里面就有我們需要的數據。
let script = document.createElement('script');script.src = 'http://www.wang.cn/login?username=wang&callback=callback';document.body.appendChild(script);function callback(res) {console.log(res); }回調函數的名字是什么?
回調的名字是可以隨機生成的的一個隨機數,我們把這個名字當成 callback 的參數傳給后臺,后臺會把這個函數再次返回給我們并執行
JSONP跨域優點
兼容ie
可以跨域
JSONP跨域缺點
由于是 script 標簽,所以讀不到 ajax 那么精確的狀態,不知道狀態碼是什么,也不知道響應頭是什么,它只知道成功和失敗。
不支持post(因為是 script 標簽,所以只支持 get 請求)
告誡自己,即使再累也不要忘記學習,成功沒有捷徑可走,只有一步接著一步走下去。 共勉!
”總結
以上是生活随笔為你收集整理的3000 字说说跨域!面试官听完之后露出了满意的笑容的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 8 中的流操作-基本使用性能测
- 下一篇: 为什么魂斗罗只有 128 KB却可以实现