發佈自 Kindem的博客,歡迎你們轉載,可是要注意註明出處。另外,該文章收納在 Kindem的我的的 IT 知識整理倉庫,歡迎 Star、Fork、投稿
所謂Ajax跨域
指的是Ajax
請求從其餘的域獲取數據或者傳輸數據html
所謂域同源,指的是兩個服務器資源的根url
的域名
、端口
、協議
三者徹底相同,只要三者中任何一個不一樣,則說明產生了跨域前端
給一個例子,對於第一個服務器資源,其餘一些url
的同源狀況以下:java
http://www.test.com/index.html http://www.test.com/index.js 同源 http://www.test.com/login/login.js 同源 https://www.test.com/index.html 跨域(協議) http://www.a.com/index.html 跨域(域名) http://a.com/index.html 跨域(不一樣子域) http://www.test.com:8080/index.html 跨域(端口)
CORS
是一個W3C
標準,其全稱爲Cross-Origin Resource Sharing
,即跨域資源共享。它容許瀏覽器向跨域服務器發送XMLHttpRequest
請求,從而克服了Ajax
只能同源使用的限制git
CORS
須要瀏覽器和服務器同時支持,目前主流瀏覽器都支持這個標準(IE
>=10),因此CORS
的關鍵主要在於服務器,要支持這個功能,每每開發者須要在服務器端進行額外設置github
另外,CORS
標準對用戶來講是透明的,用戶感知不到CORS
的存在,一切都是瀏覽器自動完成。當瀏覽器檢測到跨域的Ajax
請求時,就會自動作出一些處理,使得請求可以跨域ajax
跨域的Ajax
請求分爲兩種:json
簡單請求:跨域
HEAD
、POST
、GET
之一HTTP
頭字段只有Accept
、Accept-Language
、Content-Language
、Last-Event-ID
、Content-Type
中的一種或多種HTTP
頭字段中的Content-Type
字段的取值爲application/x-www-form-urlencoded
、multipart/form-data
、text/plain
之一CORS
對於兩種不一樣的請求的處理是不一樣的瀏覽器
對於簡單請求,一個跨域Ajax
請求的處理流程以下:
HTTP
頭中添加Origin
字段,表示此次請求來自的域服務器根據Origin
字段判斷這一次請求是否在許可範圍內:
HTTP
響應,只不過響應的HTTP
頭中沒有Access-Control-Allow-Origin
字段,瀏覽器將認爲這一次跨域Ajax
沒能成功若是在,服務器會在響應HTTP
頭中添加這幾個字段
Access-Control-Allow-Origin
: 這個字段標識服務器認同的Origin
,這個Origin
爲*
時標識服務器認同全部源。只有請求的HTTP
頭的Origin
與該字段同源時,瀏覽器纔會認爲這一次跨域Ajax
請求成功了Access-Control-Allow-Credentials
: 這個字段標識服務器容許Cookie
,若是設置爲true
則標識容許,默認爲不容許Access-Control-Expose-Headers
: 容許XMLHttpRequest
獲取的額外字段名對於非簡單請求,一個跨域Ajax
請求的處理流程以下:
瀏覽器在發送正式的Ajax
請求以前,會提早發送一次OPTIONS
請求,頭信息中有:
Origin
: 請求的源Access-Control-Request-Method
: 瀏覽器會用的的HTTP
方法Access-Control-Request-Headers
: 瀏覽器會額外發送的頭信息字段Access-Control-Allow-Origin
HTTP
響應,則瀏覽器會認爲OPTIONS
請求成功,接下來則會進行真正的的請求HTTP
響應中也帶上Access-Control-Allow-Origin
,瀏覽器會再一次校驗這一字段可見CORS
標準自己並不複雜,其核心是服務器和瀏覽器驗證域是否被容許
JSONP
的全稱爲JSON with Padding
,是JSON
數據的一種使用模式,JSONP
一樣是爲了支持跨域Ajax
請求而生的,可是它相對CORS
來講對古老的瀏覽器兼容性較好,也更加簡單。
JSONP
的原理是JavaScript
注入,在html
中使用<script>
標籤引入JavaScript
腳本是不會受到同源限制的,這意味着能夠經過<script>
標籤引入來自跨域的腳本,像這樣:
// origin: http://www.test.com <script> function dealData(jsonData) { // do something with jsonData } </script> <script src="http://www.a.com/data.js"></script>
想象一下若是引入的腳本是這樣的:
dealData({ username: 'kindem', age: 15, // ... });
不是就至關於從服務器拿到一段數據而且進行處理了嗎?
接下來能夠設想一下,假設服務器對於src
指向的url
的處理並非返回一個靜態文件,而是動態地組合出一段文本,這段文本一上面給的形式返回,裏面的參數由服務器動態生成,而調用的函數則是前端約定好的函數,則至關於變相地返回了一段跨域的數據,這就是JSONP
的核心思想