前端面試常見問題之跨域
一、同源策略
什麼是同源策略???
同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。所謂同源,就是指兩個頁面具有相同的協議,主機(也常說域名),端口,三個要素缺一不可
爲什麼會有同源???
同源策略主要是爲了保護cookie,因爲HTTP協議無狀態,想要服務端記住客戶端,則可以通過cookie和session機制,這樣客戶端請求的報文cookie中攜帶的sessionid就是客戶端在服務器的標識。JavaScript可以跨域讀取到cookie。同源策略不允許跨域發送cookie
同源策略的限制
- Cookie、LocalStorage和IndexDB無法讀取
- DOM節點無法獲取和設置
- Ajax請求不能發送
二、跨域
跨域就讀取的實現
跨域分爲:
-
跨域源數據存儲
-
Cookie跨域
-
跨窗口的跨域通信
-
XMLHttpRequest的跨域
跨域是指瀏覽器允許向服務器發送跨域請求,從而克服Ajax只能同源使用的限制。
域名相同,文件或路徑不同、端口不同、協議不同 域名和域名對應相同ip、主域相同但子域不同
常見的跨域場景:
URL 說明 是否允許
http://www.domain.com/a.js
http://www.domain.com/b.js 同一域名,不同文件或路徑 允許
http://www.domain.com/lab/c.js
http://www.domain.com:8000/a.js
http://www.domain.com/b.js 同一域名,不同端口 不允許
http://www.domain.com/a.js
https://www.domain.com/b.js 同一域名,不同協議 不允許
http://www.domain.com/a.js
http://192.168.4.12/b.js 域名和域名對應相同ip 不允許
http://www.domain.com/a.js
http://x.domain.com/b.js 主域相同,子域不同 不允許
http://domain.com/c.js
http://www.domain1.com/a.js
http://www.domain2.com/b.js 不同域名 不允許
三、常見的解決跨域的方案
1、JSONP跨域
2、nodejs中間件代理跨域
3、document.domain + iframe跨域
4、location.hash + iframe跨域
5、window.name + iframe跨域
6、postMessage跨域
7、WebSocket協議跨域
8、跨域資源共享(CORS)
9、Nginx代理跨源
四、CORS
CORS是一個W3C標準,它允許瀏覽器向跨源服務器,發出XMLHTTPRequest請求,從而克服了AJAX只能同源使用的限制。
CORS跨域請求分爲簡單請求和非簡單請求。
滿足兩個條件之一就屬於簡單請求:
使用head、get、或post
請求的Header是Accept、Accept-Language、Content-Language、Content-Type只限於三個值:application/x-www-form-urlencoded、multipart/form-data、text/plain
不同時滿足上邊兩個條件,就屬於非簡單請求。
簡單請求
對於簡單請求,瀏覽器直接發出CORS請求。簡單來說,就是直接在頭信息中添加一個Origin字段,用來說明本次請求來自哪個源(協議+域名+端口)。服務器根據這個值決定是否同意這次請求。
CORS請求設置的響應頭字段,都以Access-Control-開頭。
複雜請求
非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是put或delete,或者Content-Type字段的類型是application/json。非簡單請求 的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱爲“預檢”請求。
預檢請求用的方法是OPTIONS,表示這個請求是用來詢問的。請求頭信息裏,關鍵字段是Origin,表示這個請求來自哪個源。除了Origin字段,預檢請求的頭信息包括兩個特殊字段。
Access-Control-Request-Method:必選
用來列出瀏覽器的CORS請求會用到哪些HTTP方法。
Access-Control-Request-Headers:可選
該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段。
Nginx代理跨域
Nginx代理跨域實質和CORS跨域原理一樣,通過配置文件設置請求響應頭等字段。
Nginx配置解決iconfont跨域,在Nginx的靜態資源服務器中加入以下配置。
location / {
add_header Access-Control-Allow-Origin *;
}
Nginx反向代理接口跨域。通過Nginx配置一個代理服務器域名(與domain1相同,端口不同)做跳板機,反向代理訪問domain2接口,並且可以順便修改cookie中的domain信息,方便當前域cookie寫入,實現跨域訪問。