簡體   English   中英

IE8 - IE10跨域JSONP cookie令人頭疼

[英]IE8 - IE10 cross domain JSONP cookie headache

由於完全不受我控制的決定,我處於以下情況:

  • 我在catalog.org上有一個產品列表

  • 單擊產品上的“添加到購物車”按鈕會向Secure.com/product/add/[productKey發出AJAX JSONP請求,這會將購物車記錄保存到數據庫, 使用購物車ID設置cookie ,然后返回true響應(如果失敗則為false)

  • 回到catalog.org,如果響應為真,則向secure.com/cart/info發出另一個AJAX JSONP請求, 請求讀取購物車ID cookie ,獲取記錄,並返回購物車中的商品數量

  • 再次返回catalog.org,讀取響應並更新頁面上的元素,顯示購物車中的商品數量(如果有)

  • 此時,單擊catalog.org上的“轉到購物車”按鈕會在secure.com上顯示購物車摘要

這在Firefox 17,Chrome 32和IE 11中運行良好。它也適用於我們開發和測試環境中的IE8 - IE10,其中catalog.org是catalog.development.com,catalog.test.com和secure.com是安全的。 development.com和secure.test.com分別。

但是,在我們部署到生產之后,這停止了在IE8 - IE10中工作。 將產品添加到購物車后,購物車中的商品數量會在catalog.org上成功更新。 然后,在單擊catalog.org上的“轉到購物車”按鈕后,secure.com上的購物車摘要顯示任何內容,因為它無法讀取cookie。 在IE開發人員工具中進入緩存>“查看cookie信息”顯示沒有購物車ID cookie。 它應該存在,就像在其他瀏覽器和我們的開發和測試環境中一樣。

我相信正在發生的事情是IE阻止第三方cookie。 我們已經為secure.com上的所有請求添加了一個P3P精簡策略標頭,但cookie仍未設置。 我們設置的標題是:

P3P: CP="CAO PSA OUR"

為什么不在IE8-IE10中添加緊湊的策略頭修復此問題? 我怎樣才能解決這個問題,以便在IE的所有版本中運行?

下面有幾個好主意。 我接受了@ sdecima's,因為它聽起來最有希望。 我們最終結合了其中的一些想法,但設法避免了XDomainRequest:

  • 單擊產品上的“添加到購物車”按鈕會向Secure.com/product/add/[productKey發出AJAX JSONP請求,這會將購物車記錄保存到數據庫, 使用購物車ID設置cookie ,然后返回true響應(如果失敗則為false)

我們在secure.com/product/add上更改了操作,以返回一個JSON對象,其中包含指示成功或失敗的布爾值以及購物車ID。

  • 回到catalog.org,如果響應為真,則向secure.com/cart/info發出另一個AJAX JSONP請求, 請求讀取購物車ID cookie ,獲取記錄,並返回購物車中的商品數量

我們更改了回調函數以檢查響應對象中的兩個屬性。 如果成功,並且存在購物車ID,我們會在頁面上創建隱藏的iframe。 iframe的src屬性設置為我們添加到secure.com的新端點。 此操作接受購物車ID參數並保存購物車ID Cookie。 我們不再需要在secure.com/product/add操作中保存cookie。

接下來,我們更改了secure.com/cart/info上的操作以接受購物車ID參數。 此操作將使用購物車ID參數(如果存在)來獲取購物車信息,否則它仍將嘗試讀取cookie。 如果我們可以保證iframe已經完成加載並且cookie已經保存在secure.com上,那么這個額外的檢查將是不必要的,但是由於瀏覽器安全限制,我們無法知道iframe何時在catalog.org上完成加載。

最后,仍然需要P3P標題CP="CAO PSA OUR"才能在IE7-IE10中工作。 (是的,這也適用於IE7 :)

我們現在有一個解決方案(盡管是一個非常復雜的解決方案),用於保存和訪問適用於所有主流瀏覽器的跨域cookie,至少在我們能夠可靠測試的時候。

我們可能會對此進行一些重構。 首先,此時對secure.com/cart/info的第二個AJAX JSONP請求是多余的,因為我們可以將原始請求中所需的所有信息返回到secure.com/product/add操作(更改的附帶好處)該操作返回一個JSON對象 - 加上我們可以返回一條錯誤消息,指出如果出現錯誤則確切失敗的原因)。

簡而言之

Cookie不會在IE 8和9上通過跨源請求。但它應該適用於IE 10和11。


IE 8和9

在IE8 / 9上, XMLHttpRequest部分支持CORS ,並且在XDomainRequest對象的幫助下進行跨源請求,該對象不向每個請求發送cookie。

您可以在以下官方MSDN博客文章中閱讀有關此內容的更多信息:
http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

特別是這部分:

5。 不會隨請求一起發送身份驗證或Cookie

為了防止濫用用戶的環境權限(例如cookie,HTTP憑證,客戶端證書等), 請求將被剝離cookie和憑據,並將忽略HTTP響應中的任何身份驗證質詢或Set-Cookie指令 XDomainRequests不會在以前經過身份驗證的連接上發送,因為某些Windows身份驗證協議(例如NTLM / Kerberos)是基於每個連接而不是基於請求的。

IE 10+

從IE10開始, XMLHTTPRequest中添加了完整的CORS支持,它應該可以正常使用來自服務器的響應的正確的Access-Control-Allow-Origin標頭屬性(希望在瀏覽器上設置cookie)。

更多相關信息:
http://blogs.msdn.com/b/ie/archive/2012/02/09/cors-for-xhr-in-ie10.aspx
和這里:
http://www.html5rocks.com/en/tutorials/cors/

IE 8和9的變通方法

在IE8 / 9上解決這個問題的唯一方法是引用與上面相同的MSDN帖子

希望對跨源請求執行用戶身份驗證的站點可以使用顯式方法(例如POST正文或URL中的令牌)來傳遞此身份驗證信息,而不會冒用戶的環境權限。

結論:第三方cookie通常被隱私/廣告攔截擴展程序阻止,應被視為不可靠。 你會在腳下射擊,讓它繼續生產。

語法表明端點有一天會成為RESTful的野心。 唯一的問題是使用cookie,它會將整個“無狀態”概念拋到窗外! 理想情況下,應對API進行更改。 如果您沒有與第三方集成(即“secure.com”由您的公司運營),這絕對是處理該問題的正確方法。

cartIdsecure.com cookie移到其查詢字符串中:

secure.com/product/add/9876?cartId=1234    //should be a POST

從哪里獲得有效的cartId值? 我們可以將其保留在目錄域的一些secure-com-cart-id cookie集中,這將避免任何跨域問題。 檢查該值,如果存在,則附加到每個secure.com請求,如上所述:

$.post('secure.com/product/add/9876', {    //needs jQuery.cookie
  cartId: $.cookie('secure-com-cart-id')
});

如果您沒有有效的cartId ,請將其視為新用戶,並在沒有參數的情況下發出請求。 然后,您的API應分配一個新ID並在響應中返回它。 然后可以更新“本地” secure-com-cart-id cookie。 沖洗並重復。

瞧,你剛剛持有一個活躍的用戶購物車而沒有用cookie來污染API調用。 對你的建築師大喊大叫。 如果你不能這樣做(改變API語法或大喊大叫),你將不得不建立一個到secure.com端點的隧道,這樣就不會有跨域請求 - 基本上就是在catalog.org/secure- com-endpoint將把請求逐字地傳遞secure.com 這是一種專門用於避免對API進行更改的解決方法,只是不要使用代碼並設置適當的Apache / IIS / F5規則來代替它。 快速搜索提出了幾個解釋, 這個看起來對我很好。

PS:在我看來,這是一個經典的XY問題 解決方案不一定是關於持久存在第三方cookie,而是將必要參數傳遞給第三方,同時將數據保存在某處

雖然正確的解決方案是改變架構,但如果您正在尋找一種快速,臨時的解決方案:

JSONP文件實際上只是javascript。 您可以添加一行代碼以將Cookie設置到JSONP的前面。

例如,而不是:

callback({"exampleKey": "exampleValue"});

您的JSONP可能如下所示:

document.cookie="cartID=1234";
callback({"exampleKey": "exampleValue"});

如果您控制DNS記錄,請創建一個新條目,以便兩個服務器位於同一個域中。

是否有1個數據庫服務於catalog.org和secure.com,還是可以進行通信?

如果是這樣的話,你就明白了。

當catalog.org服務器cookie時,將其保存在db中。 當secure.com服務器cookie時,將其保存在db中。 然后,您可以確定哪個購物車屬於哪個用戶。

這是一個值得考慮的有趣問題......更新2:

當用戶訪問catalog.org時:

  • 檢查他是否有cat_org cookie,如果沒有,則:

    • 在catalog.org中:

      • 創建一個鍵值對並保存在db {cat_cookie_id,unique_number}中
      • 在瀏覽器中設置cat_cookie_id
      • 指示瀏覽器訪問ajax訪問secure.com/register/unique_number
    • 在secure.com

      • 從url讀取unique_number
      • 創建secure_cookie id
      • 保存在db {cat_cookie_id,unique_number,secure_cookie_id}中
      • 刪除unique_number,因為這是一次性使用密鑰

現在,db可以將cat_cookie_id映射到secure_cookie_id,反之亦然。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM