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