什麼是跨域?前端
同源:協議、域名、端口相同。不一樣源便是跨域。兩個不一樣的域名即便指向同一個IP地址,也不一樣源。nginx
同源策略限制的內容有哪些?json
DOM 層面:限制了不一樣源 JavaScript 對當前 DOM 對象的讀寫操做;canvas
數據層面:限制了不一樣源站點讀取當前站點的 Cookie、IndexDB、LocalStorage 等數據;segmentfault
網絡層面:限制了經過 XMLHttpRequest 等方式將站點的數據發送給不一樣源的站點。跨域
容許跨域的三個標籤瀏覽器
<img>
、<link>
、<script>
服務器
跨域的解決方案有哪些?網絡
(1) 同源策略限制下請求接口的方式:app
JSONP
<script>
標籤的src
屬性來實現跨域。<script>
標籤的src
屬性,所以只支持 get 方法。空iframe
加form
iframe
元素和form
元素;iframe
的load
事件處理程序中添加相應代碼;form
元素的action
屬性爲請求的url
,method
屬性爲post
,target
屬性爲iframe
的name
,最後調用form
的submit()
方法發送請求。CORS
分爲簡單請求和應當先發送預檢請求的請求。簡單請求設置Origin
頭部,服務器返回響應數據時設置Access-Control-Allow-Origin
頭部。非簡單請求先發送預檢請求,預檢請求完成後再發送實際請求。
代理
使用nginx
代理配置 server_name 爲請求發起方的域名,而後設置location
攔截前端的跨域請求,再將請求代理到服務器域名便可繞過瀏覽器的同源策略。
WebSocket
(2) 同源限制下Dom查詢的方式
postMessage
使用 HTML5 提供的postMessage()
方法能夠實現不一樣頁面的跨域通信。在頁面中使用postMessage()
發送消息,使用addEventListener()
監聽回覆的消息。
document.domain
適用於主域名相同,子域名不一樣的iframe
跨域。給兩個頁面指定document.domain = 主域名
便可訪問對方的window
對象了。
canvas
操做圖片的跨域問題
跨域的圖片只要能在網頁中正常顯示,就可使用canvas
的drawImage()
方法繪製出來。可是若是要對圖片進行getImageData()
或toDataURL()
操做,則須要處理跨域問題。
Access-Control-Allow-Origin
頭部,容許請求發送方訪問Image
實例後,設置實例的crossOrigin
屬性值爲''
(crossOrigin
的屬性值不爲use-credentials
時,所有都會解析爲anonymous
,表示不須要攜帶任何非匿名信息給服務器)什麼是 CORS ?
CORS 即跨域資源共享標準,它新增了一組 HTTP 首部字段,容許服務器聲明哪些源站經過瀏覽器有權限訪問哪些資源。另外,對可能對服務器數據產生反作用的 HTTP 請求方法,瀏覽器必須先使用OPTIONS
方法發起一個預檢請求,從而獲知服務端是否容許該跨域請求。服務器確認容許以後,才發起實際的 HTTP 請求。在預檢請求的返回中,服務器端也能夠通知客戶端,是否須要攜帶身份憑證。
CORS 的三個訪問控制場景
(1) 簡單請求知足如下全部條件:
使用的請求方法爲GET
、HEAD
、POST
中的一種;
首部字段僅限於Accept
、Accept-Language
、Content-Language
、Content-Type
、DPR
、Downlink
、Save-Data
、Viewport-Width
和Width
所組成的集合中的元素;
Content-Type
值爲text/plain
、multipart/form-data
、application/x-www-form-urlencoded
中的一個;
請求中的任意XMLHttpRequestUpload
對象都沒有註冊任何事件監聽器;
請求中沒有使用ReadableStream
對象。
簡單請求中頭部字段Origin
值爲本身的域名,響應頭部攜帶字段Access-Control-Allow-Origin
,值爲包含請求域名的值或*
,這樣便可完成跨域請求。
(2) 應當先發送預檢請求的請求知足下述任一條件:
PUT
、DELETE
、CONNECT
、OPTIONS
、TRACE
、PATCH
中的一種;Accept
、Accept-Language
、Content-Language
、Content-Type
、DPR
、Downlink
、Save-Data
、Viewport-Width
、Width
以外的字段;Content-Type
值不屬於application/x-www-form-urlencoded
、multipart/form-data
、text-plain
之一;XMLHttpRequestUpload
對象註冊了任意多個事件監聽器;ReadableStream
對象。發送一個使用OPTIONS
方法的預檢請求,用以從服務器獲取更多信息。預檢請求完成以後,發送實際請求。
// 預檢請求頭部,這些頭部無須手動設置,使用XMLHttpRequest對象發起跨域請求時,它們已經被設置就緒
Origin: 請求來源
Access-Control-Request-Method: 實際請求將使用的方法
Access-Control-Request-Headers: 實際請求將使用的自定義首部字段
// 預檢請求響應頭部
Access-Control-Allow-Origin: 容許訪問的域名
Access-Control-Allow-Methods: 容許使用的請求方法
Access-Control-Allow-Headers: 容許使用的自定義首部
Access-Control-Max-Age: 響應的有效時間。在有效時間內,瀏覽器無須爲同一請求再次發起預檢請求
複製代碼
(3) 附帶身份憑證的請求
XMLHttpRequest
請求須要將withCredentials
標識設置爲true
,Fetch
請求須要將credentials: 'include'
添加到fetch()
方法的init
對象中。響應頭部中須要攜帶Access-Control-Allow-Credentials: true
頭部,不然瀏覽器不會把響應內容返回給請求發送者。Access-Control-Allow-Origin
的值爲*
,若是設置了會致使請求失敗。參考: