瀏覽器的同源策略是瀏覽器上爲安全性考慮實施的很是重要的安全策略。
從一個域上加載的腳本不容許訪問另一個域的文檔屬性。
舉個例子:好比一個惡意網站的頁面經過iframe嵌入了銀行的登陸頁面(兩者不一樣源),
若是沒有同源限制,惡意網頁上的javascript腳本就能夠在用戶登陸銀行的時候獲取用戶名和密碼。
何謂同源:URL由協議、域名、端口和路徑組成,若是兩個URL的協議、域名和端口相同,則表示它們同源。
在瀏覽器中,<script>、<img>、<iframe>、<link>等標籤均可以加載跨域資源,而不受同源限制,
但瀏覽器會限制腳本中發起的跨域請求。好比,使用 XMLHttpRequest 對象和Fetch發起 HTTP 請求就必須遵照同源策略。
Web 應用程序經過 XMLHttpRequest 對象或Fetch能且只能向同域名的資源發起 HTTP 請求,而不能向任何其它域名發起請求。
不容許跨域訪問並不是是瀏覽器限制了發起跨站請求,而是跨站請求能夠正常發起,可是返回結果被瀏覽器攔截了。
最好的例子是CSRF跨站攻擊原理,請求是發送到了後端服務器,不管是否設置容許跨域,
有些瀏覽器不容許從HTTPS跨域訪問HTTP,好比Chrome和Firefox,這些瀏覽器在請求還未發出的時候就會攔截請求,這是特例。
克服跨域限制的方法有(實踐中後兩種最經常使用,因此重點介紹):
(1)經過jsonp跨域
(2)經過修改document.domain來跨子域
(3)使用window.name來進行跨域
(4)使用HTML5中新引進的window.postMessage方法來跨域傳送數據
(5)使用代理服務器,使用代理方式跨域更加直接,由於同源限制是瀏覽器實現的。若是請求不是從瀏覽器發起的,就不存在跨域問題了。
使用本方法跨域步驟以下:
1. 把訪問其它域的請求替換爲本域的請求
2. 服務器端的動態腳本負責將本域的請求轉發成實際的請求
爲了經過Ajax從http://localhost:8080訪問http://localhost:8081/api,能夠將請求發往http://localhost:8080/api。
而後利用Apache Web服務器的Reverse Proxy功能作以下配置:ProxyPass /api http://localhost:8081/api
(6)CORS全稱是"跨域資源共享"(Cross-origin resource sharing),CORS須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能
(IE瀏覽器不能低於IE10),所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。
瀏覽器將CORS請求分紅兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)
(1) 請求方法是如下三種方法之一:HEAD GET POST
(2)HTTP的頭信息不超出如下幾種字段:Accept Accept-Language Content-Language Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不一樣時知足上面兩個條件,就屬於非簡單請求。
對於簡單請求,瀏覽器在發出CORS請求時會在頭信息之中增長一個Origin字段。服務器的返回會多出3個字段:
Access-Control-Allow-Origin(必須) 容許跨域的源
Access-Control-Allow-Credentials(可選) 表示是否容許發送Cookie。默認狀況下,Cookie能夠包含在請求中,一塊兒發給服務器
若是服務器不須要瀏覽器發送Cookie,刪除該字段便可。
Access-Control-Expose-Headers(可選) CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:
Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其餘字段,
就必須在Access-Control-Expose-Headers裏面指定。如指定Access-Control-Expose-Headers: FooBar,則可經過
getResponseHeader('FooBar')獲取FooBar字段的值。
非簡單請求是那種對服務器有特殊要求的請求,好比請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)。
"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問的。頭信息裏面,關鍵字段是Origin,表示請求來自哪一個源。
瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,
瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。javascript