在瞭解跨域這個概念以前首先要知道的是何爲同源策略。所謂的同源是一種安全機制,爲了預防某些惡意行爲(例如 Cookie 竊取等),瀏覽器限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。而知足同源要具有三方面:協議相同、域名相同、端口相同。javascript
如下是對於http://domain.com/dir/index.html
(默認端口 80)來進行同源判斷:html
http://domain.com/dir2/info.html
(同源)https://domain.com/dir/index.html
(非同源,協議不相同)http://www.domain.com/dir/index.html
(非同源,域名不一樣)http://domain.com:233/dir/index.html
(非同源,端口不一樣)同源策略對於用戶信息安全是必不可少的,可是實現合理的跨域請求也是很重要的,因而 W3C 就定了一個叫CORS(Cross-Origin Resource Sharing)的草案,也就是跨域資源共享。其基本思想就是使用自定義的 HTTP 頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功或是失敗。java
實現 CORS 須要瀏覽器與服務器的同時支持。例如發送一個簡單的GET
或POST
請求,瀏覽器會爲其添加一個Origin
的頭,其包含頁面的源信息(協議、域名和端口),如:jquery
Origin: http://domain.com
複製代碼
若服務器認爲該請求可接受,就在Access-Control-Allow-Origin
頭部中回發相同的源信息(咱們有時調用的公共 API,大部分都是將該頭部設爲*
,可是它們都不發送 Cookie)。要注意的是請求和響應都不包含 Cookie 信息。nginx
以上都爲簡單請求,對於非簡單請求,CORS 經過一種叫作 Preflighted Requests 的透明服務器驗證機制支持開發者使用自定義頭部信息或者 GET 和 POST 以外的方法,不過代價是在正式通訊前增長一次 HTTP 請求,這裏就不詳細描述了。ajax
現代瀏覽器都對 CORS 提供了原生支持(IE八、9 是利用XDomainRequest
,不過已廢棄),無需編寫額外代碼便可觸發簡單的跨域行爲,由於瀏覽器會自動幫你添加一些頭部信息,可是有如下限制:json
setRequestHeader()
設置自定義頭部。Access-Control-Allow-Credentials
設爲true
。getAllResponseHeaders()
會返回空字符串。該跨域技術主要是利用<img>
標籤設置src
屬性(請求地址一般都帶有查詢字符串),而後監聽該<img>
的onload
或onerror
事件來判斷請求是否成功。響應的內容一般是一張 1 像素的圖片或者204
響應。跨域
圖片 Ping 有兩個缺點:瀏覽器
<img>
標籤實現,因此只支持GET
請求。因爲以上特色,圖片 Ping 方法經常使用於跟蹤用戶點擊頁面或動態廣告的曝光次數。安全
JSONP 是 JSON with padding 的簡寫,其主要是利用動態建立<script>
標籤向服務器發送 GET 請求,服務器收到請求後將數據放在一個指定名字的回調函數中並傳送回來。接下來看一下簡單示例: 瀏覽器:
//對建立標籤行爲進行封裝
function addScriptTag(src) {
var script = document.createElement('script')
script.setAttribute("type","text/javascript")
script.src = src
document.body.appendChild(script)
}
//當瀏覽器加載完畢時向服務器發送請求
window.onload = function () {
addScriptTag('http://domain.com/data?callback=getdata')
}
//服務器收到上面的請求後,將數據放在回調函數的參數(data)中返回
function getdata(data) {
console.log(data)
}
複製代碼
jQuery 也有對 JSONP 的封裝,有興趣的能夠了解一下(文章尾部連接)
服務器
//服務器獲取參數名後,將回調函數和參數拼接爲字符串返回
response.send(
`${query.callback}({ "name": "Hello" })`
)
複製代碼
跨域方法其實還有很多,這裏先總結這麼多,日後若時間容許的話就更新 😬