摘要:但是如果是一級域名相同,二級及以上域名不同的網(wǎng)頁可以通過設(shè)置來共享。設(shè)置有兩種方式前端腳本中設(shè)置服務(wù)器接口設(shè)置時指定所屬的域名為一級域名。服務(wù)器檢查過預檢請求頭之后,確認允許跨域請求,就可以做出回應(yīng)。
一、跨域問題產(chǎn)生的原因
根本原因是由于瀏覽器的“同源政策”。
同源政策由網(wǎng)景公司(Netscape)1995年引入瀏覽器。目前所有瀏覽器都實行這個政策。
所謂同源是指“三個相同”:
協(xié)議相同
域名相同
端口相同
目前,如果非同源,共有三種行為收到限制。
Cookie、LocalStorage 和 IndexDB 無法讀取。
DOM無法獲取
AJAX請求不能發(fā)送
二、跨域問題處理Cookie是服務(wù)器寫入瀏覽器的信息,只有同源的網(wǎng)頁才能共享。但是如果是一級域名相同,二級(及以上)域名不同的網(wǎng)頁可以通過設(shè)置document.domain來共享cookie。
比如,w1.example.com 和 w2.example.com是不同源的,w1.example.com/index.html (A網(wǎng)頁) 和 w2.example.com/index.html (B網(wǎng)頁)只要設(shè)置相同的document.domain就可以共享Cookie。
設(shè)置domain有兩種方式:1.前端js腳本中設(shè)置 2.服務(wù)器接口設(shè)置cookie時指定Cookie所屬的域名為一級域名。
在A網(wǎng)頁設(shè)置
document.domain = “example.com”; document.cookie = “userName = aaa”;
這樣在B網(wǎng)頁就可以讀到這個Cookie
var cookie = document.cookie; // userName = aaa;
Set-Cookie: userName = aaa ; domain = .example.com ; path = /
如果兩個網(wǎng)頁不同源,就無法拿到對方的DOM。典型例子是iframe和window.open方法打開的窗口,它們與父窗口無法通信。
如果兩個窗口只是二級域名不同,一級域名相同的話,那么設(shè)置document.domain屬性,就可以規(guī)避同源政策。拿到DOM。對于完全不同源的網(wǎng)站,目前有三種方法可以解決跨域窗口通信問題:
片段標識符
window.name
跨文檔通信API
片段標識符指的是URL的#后面的部分,如http://example.com/index.html...。如果只是改變片段標識符部分,頁面不會刷新。
父窗口可以把信息寫入子窗口的片段標識符中,
var src = originURL + ‘#’ + data; document.getElementById(‘#iframe’).src = src;
子窗口通過監(jiān)聽hashchange事件得到通知
window.onhashchange = checkMessage; function checkMessage(){ var message = window.location.hash; //... }
同樣子窗口也可以修改父窗口的片段標識符。
parent.location.href = target + ‘#" + hash;
瀏覽器窗口有window.name屬性。這個屬性最大的特點是,無論是否同源,只要在同一個窗口里,前一個網(wǎng)頁設(shè)置了這個屬性,后一個網(wǎng)頁就可以讀取它。
postMessage是HTML5引入的一個全新的API:跨文檔通信API提供的一個全局方法,允許跨窗口通信,不論是否同源。
父窗口發(fā)送message
var popup = window.open(‘http://aaa.com’,"title"); popup.postMessage(‘Hello World’, ‘http://aaa.com");
子窗口監(jiān)聽message事件
window.addeventlistener(‘message’,function( e ){ console.log( e.data ); });
message事件的event對象提供三個屬性
event.source 發(fā)送消息的窗口
event.origin 消息發(fā)向的網(wǎng)址
event.data 消息內(nèi)容
用window.postMessage可解決。
同源政策規(guī)定,AJAX只能發(fā)給同源的網(wǎng)址,否則會報錯。除了用服務(wù)器代理的方法(nginx反向代理等),有以下方法可以解決。
原理是利用script標簽的src屬性,接受JSON數(shù)據(jù)。關(guān)鍵在于規(guī)定一個callback方法名,在url中以參數(shù)形式傳給服務(wù)器,由服務(wù)器將數(shù)據(jù)以參數(shù)形式注入callback中,供js腳本使用。
缺點是只能發(fā)送get請求,優(yōu)點是支持老式瀏覽器。
CORS即跨源資源分享,是W3C標準,是跨源AJAX請求的根本解決方法。相比JSONP,CORS允許任何類型的請求。
目前除了IE之外的所有瀏覽器都支持CORS,IE不能低于IE10版本。
瀏覽器將CORS請求分為兩類,簡單請求和非簡單請求。
簡單請求條件:
1. 請求方法 GET、POST、HEAD; 2. http頭信息不超過 Accept 、Accept-Language 、Content-Language、Last-Event-ID; 3. content-type只限于三個值: application/x-www-form-urlencoded、multipart/form-data、text/plain
對于簡單請求,瀏覽器的處理是直接發(fā)出CORS請求,也就是在頭信息中增加一個字段Origin,該字段說明本次請求是來自哪個源(協(xié)議+域名+端口)。服務(wù)器根據(jù)這個值,判斷是否同意此次請求。
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
如果Origin指定的域名在許可范圍內(nèi),服務(wù)器返回的相應(yīng),會多幾個頭信息字段。
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin:該字段必須,它的值要么是請求是Origin的值,要么是一個*,表示接受任意域名的請求。
Access-Control-Allow-Credentials:該字段可選。值是一個布爾值,表示是否允許發(fā)送Cookie,默認為true,表示可以發(fā)送。
Access-Control-Expose-Headers:該字段可選。CORS請求是XHR對象的getResponseHeader( ) 方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expire、Last-Modified、Pragma。如果想要拿到其他字段,就要在Access-Control-Expose-Headers中指定。
注意,如果要將Cookie發(fā)送到服務(wù)器,除了服務(wù)器要設(shè)置Access-Control-Allow-Credentials字段以外,瀏覽器在發(fā)送AJAX請求是也要保證xhr.withCredentials屬性為true,否則瀏覽器既不會向服務(wù)器發(fā)送cookie,服務(wù)器設(shè)置cookie的操作也不會成功。但是默認情況下,該屬性是為true的。
另外需要注意的是,如果要操作Cookie,Access-Control-Allow-Origin就不能設(shè)置為*,必須明確是哪個網(wǎng)址過來的請求。
對于非簡單請求:
非簡單請求的CORS請求,會在正式通信之前,增加一次HTTP請求,成為“預檢”請求。
瀏覽器先詢問服務(wù)器,當前網(wǎng)頁所在域名是否在服務(wù)器的許可名單中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會發(fā)出正式的XMLHttpRequest請求,否則報錯。
預檢請求的方法是OPTIONS,頭信息中的關(guān)鍵字是Origin,標識請求來自哪個源。另外還包含兩個特殊字段:
Access-Control-Request-Method:該字段是必須的,用于流出瀏覽器的CORS請求會用到那些HTTP方法。
Access-Control-Request-Headers:該字段用來指定CORS會額外發(fā)出的頭信息字段。
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
服務(wù)器檢查過預檢請求頭之后,確認允許跨域請求,就可以做出回應(yīng)。
響應(yīng)頭部信息的關(guān)鍵字段是Access-Control-Allow-Origin,為*或者一個完整域名,表示允許的請求來源。
如果服務(wù)器否定了“預檢”請求,會返回一個正常的HTTP回應(yīng),不包含任何CORS相關(guān)的字段。這是瀏覽器會認定,服務(wù)器不同意預檢請求,因此會觸發(fā)一個錯誤,唄XHR對象的onerror函數(shù)捕獲。并在控制臺打印。
成功的話還有幾個與CORS相關(guān)的響應(yīng)頭字段:
Access-Control-Allow-Methods:必須。表示服務(wù)器支持的跨域請求方法。注意會返回所有支持的方法,以此避免多次預檢請求。
Access-Control-Allow-Headers:如果請求頭包含該字段,則服務(wù)器響應(yīng)也是必須的。
Access-Control-Allow-Credentials:是否支持cookie傳輸
Access-Control-Max-Age:可選。用來指定本次預檢請求的有效期,單位為秒。在此期間不用發(fā)出另一條預檢請求。
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
一旦服務(wù)器通過了預檢請求,以后每次瀏覽器正常的CORS請求,就和簡單請求一樣,會有一個Origin字段,服務(wù)器回應(yīng)也會有一個Access-Control-Allow-origin頭信息字段。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90154.html
摘要:跨域的產(chǎn)生不用多講,作為一名前端開發(fā)人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。 跨域,相信大家無論是在工作中還是在面試中經(jīng)常遇到這個問題,常常在網(wǎng)上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。 跨域的產(chǎn)生 ...
摘要:跨域的產(chǎn)生不用多講,作為一名前端開發(fā)人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。 跨域,相信大家無論是在工作中還是在面試中經(jīng)常遇到這個問題,常常在網(wǎng)上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。 跨域的產(chǎn)生 ...
摘要:跨域的產(chǎn)生不用多講,作為一名前端開發(fā)人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的。瀏覽器引入同源策略主要是為了防止,攻擊。其指明了實際請求所允許使用的方法。 跨域,相信大家無論是在工作中還是在面試中經(jīng)常遇到這個問題,常常在網(wǎng)上看到別人所整理的一些方法,看似知道是怎么回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這里,通過自己認真思考整理一些常用的方法。 跨域的產(chǎn)生 ...
摘要:因為同源策略的限制,我們不能在與外部服務(wù)器進行通信的時候使用。這個是跨域服務(wù)器取數(shù)據(jù)的接口,參數(shù)為回調(diào)函數(shù)的名字,返回的格式為原理首先在客戶端注冊一個然后把的名字傳給服務(wù)器。 一、同源策略 同源策略,它是由Netscape提出的一個著名的安全策略,現(xiàn)在所有的可支持javascript的瀏覽器都會使用這個策略。 為什么需要同源策略,這里舉個例子: 假設(shè)現(xiàn)在沒有同源策略,會發(fā)生什么事...
摘要:同源策略做了很嚴格的限制,但是在實際的場景中,又確實有很多地方需要突破同源策略的限制,也就是我們常說的跨域。使用跨域由于同源策略,一般來說位于的網(wǎng)頁無法與不是的服務(wù)器溝通,而的元素是一個例外。 本菜雞最近在寫某個頁面請求數(shù)據(jù)時,報了如下的錯誤。 Failed to load https://...:No Access-Control-Allow-Origin header is pre...
閱讀 2206·2021-11-18 10:02
閱讀 3305·2021-11-11 16:55
閱讀 2709·2021-09-14 18:02
閱讀 2449·2021-09-04 16:41
閱讀 2079·2021-09-04 16:40
閱讀 1209·2019-08-30 15:56
閱讀 2226·2019-08-30 15:54
閱讀 3176·2019-08-30 14:15