2013-03-01 72 views
5

假設我控制兩個域,即www.api_domain.comwww.website_domain.comwww.api_domain.com提供了一個API,要求用戶進行身份驗證,然後使用會話Cookie來識別發出請求的用戶。 www.website_domain.comwww.api_domain.com將腳本加載到其頁面上,並且該腳本想用當前用戶的cookie撥打www.api_domain.com上的API URL並在www.website_domain.com的頁面上以某種方式使用結果。沒有iframe的IE 8和9的跨域cookie?

;初始加載腳本,或者不需要用戶的會話cookie來工作的任何API網址,最簡單的方法是簡單地從www.api_domain.com響應使用

Access-Control-Allow-Origin: http://www.website_domain.com 

頭。這似乎在除了IE之外的所有瀏覽器中都可以使用,儘管IE不會遵守使用jQuery的AJAX方法進行的AJAX請求中的Allow-Origin頭部,但有些類似於xdr.js的庫在後臺執行一些魔術,使jQuery,IE和Allow-Origin頭文件在一起很好地運行,並且在所有其他瀏覽器中表現得很像(我不知道xdr.js的具體細節,但是對於非憑證請求我可以很好地工作)。

問題出現在我想要訪問需要用戶會話cookie的http://www.api_domain.com上的URL。當這個問題在瀏覽器無關的設置進行了討論,兩種解決方案通常建議:

  1. 從 響應使用Access-Control-Allow-Credentials: true做餅乾甚至跨域請求被髮送。
  2. http://www.website_domain.com原產 http://www.api_domain.com在頁面上創建一個iframe,有兩個窗口使用HTML5 post messages與 相互通信,並委派發出請求http://www.api_domain.com到 iframe的所有 責任。

我會非常喜歡,如果可以使用選項1,因爲它可以讓你寫你的JavaScript代碼,你會寫這倒好同域的API相同的方式使用API​​上http://www.api_domain.com。要使用iframe方法,我們需要學習或創建一些框架,用於向iframe發送類似AJAX的請求,並帶有成功和錯誤處理程序。這也意味着我們需要創建要加載到iframe中的代碼,這只是用於訪問API URL的整個精簡包裝器。它看起來比第一種方法更醜陋,更棘手,更難理解。

但是,我不知道如何使選項1工作在IE瀏覽器。我在我的API網址上設置了Access-Control-Allow-Credentials: true,所有其他瀏覽器都向這些網址發送了cookie,但即使使用xdr.js庫,IE 9也不會。 (我還沒有在IE 8上測試過)。沒有任何其他症狀可以報告。當我在IE的開發人員工具中查看它們時,我可以在www.api_domain.com的響應中看到正確的Access-Control-Allow-OriginAccess-Control-Allow-Credentials標題,但請求中沒有cookie標頭。

是否存在一些黑客或魔法咒語,我可以使Internet Explorer尊重Access-Control-Allow-Credentials標題,或者我可以使用IE的其他標題識別?

+1

設置p3p隱私策略有幫助嗎? http://stackoverflow.com/questions/2666376/copying-cookies-cross-domain-why-is-ie-blocking-cookies-other-browsers-are-send?rq=1 – flup 2013-03-08 20:44:19

+0

@flup Nope,這是完全不相干的這個。 – 2014-04-20 11:15:31

+0

另一方面,這無助於回答這個問題,但可能對任何讀者都有用:而不是製作自己的代理iframe,考慮使用[this library](https://github.com/jpillora/xdomain/) 。我沒有對它進行測試,但它看起來應該透明地完成通過郵件爲您提供代理跨域AJAX流量的所有工作。除非您另外需要supercookie支持來處理越來越多的默認情況下阻止「第三方」cookie的瀏覽器(包括在iframe中設置的cookie),它應該是足夠的。 – 2014-04-20 11:28:23

回答

9

選項1在IE9或更低版本中是不可能的,因爲不支持使用XMLHttpRequest的CORS。此外,如果您嘗試使用XDomainRequest,則您將永遠無法隨您的請求一起發送任何Cookie。我多次在這個道路上努力編寫一個用於測試用例的ui測試庫。你想要做的只是不可能以這種方式。

這裏是一個後由Eric法,一名前微軟開發者,在詳細討論這個問題: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

的有關章節,這清楚地表明瞭CORS請求發送的cookie中IE 8是不可能的, 9,如下所示:

在Internet Explorer 8中引入了XDomainRequest對象。此對象允許AJAX應用程序直接創建安全的跨源請求,方法是確保只有當數據源指示響應爲公共時,才能通過當前頁面讀取HTTP響應;這樣,同源策略安全保證就受到保護。響應表明他們願意通過包含具有值*的訪問控制 - 允許源HTTP響應標頭或調用頁面的確切來源來允許跨域訪問。

在設計新對象時,確保現有網站和服務不會受到威脅是我們的首要任務。爲此,我們對可以使用XDomainRequest對象進行哪些請求施加了許多限制。

...

5:未認證或Cookie將與請求

發送爲了防止用戶的周圍濫用權力(如餅乾,HTTP的憑證,客戶端證書等),該請求將被刪除Cookie和憑據,並且將忽略HTTP響應中的任何認證挑戰或Set-Cookie指令。由於某些Windows身份驗證協議(例如NTLM/Kerberos)是基於每個連接而不是基於每個請求的,因此XDomainRequests不會在先前通過身份驗證的連接上發送。

希望對用戶進行跨源請求認證的站點可以使用顯式方法(例如POST主體或URL中的令牌)傳遞此認證信息而不會冒用戶的環境權限。

現在假設您可以控制的位置,你大概可以創建一個服務器到服務器的認證過程,並着手通過從域提供各種各樣的會話ID,對於其他領域,其中的客戶實際上是在通過你的申請。這並不漂亮,但它的工作原理。文章中也提到了這種方法。你會想要小心,因爲它會打開會話劫持的可能性。

+0

真棒鏈接,謝謝。清楚表明這是不可能的。服務器到服務器認證似乎比使用iframe更加笨拙的解決方案,所以我現在堅持使用iframe解決方案。 – 2013-03-10 16:01:36

0

IE8 +有XMLHttpRequest的替代方案,它支持的憑據是XDomainRequest。無論如何,XDomainRequest不是由JQuery實現的,因爲它的功能比XMLHttpRequest提供的功能少,但是有像jQuery CORS Plugin這樣的插件可以提供您需要的功能。

jQuery插件,透明地增加了跨源資源共享 (CORS)之間的瀏覽器包括IE8 +,允許跨域Ajax請求 與cookies和頭部的支持。

我也想到但不確定IE不支持Access-Control-Allow-Origin: *等標頭中的通配符。

+0

我們不使用通配符;根據CORS規範,您無法在任何瀏覽器中使用具有憑證請求的通配符。您鏈接到的github回購看起來很有前途,但我有點困惑。那裏有Java和Javascript,沒有使用說明;是這樣的想法,即Javascript只能與Java服務器一起使用,以某種方式處理請求? – 2013-03-10 00:12:01

+0

其實我還沒有嘗試過,我認爲java只是用於服務器端測試。你也可以檢查這個https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest – 2013-03-10 00:25:05