1. 程式人生 > 其它 >記SameSite屬性導致的跨域攜帶Cookie丟失

記SameSite屬性導致的跨域攜帶Cookie丟失

平臺一直使用一套騷操作來完成了單點登入,主要利用跨域cookie來獲取redis中快取的使用者資訊來判斷是否登入;突然有天失效了,於是有了此文;

平臺背景:

  1. 現有A、B兩個平臺,A登入後,將使用者登入資訊放入redis並獲取到key,將key存入http://A/user/的Cookie下;
  2. B平臺登入的時候跨域呼叫http://A/user/auth/acquire請求,此請求會攜帶這個域下的Cookie
  3. 後臺服務拿到Cookie中的key去reids查詢到登入資訊,返回登入成功;
  4. 完成整個的單點登入邏輯;

翻車現場:

  • 測試提出單點登入失效,在A平臺登入成功後,訪問B平臺仍然需要登入;

於是開始排查:

  1. 檢視A平臺登入後,http://A/user/的Cookie下存在key, 此處沒有問題;
  2. 訪問B平臺時,B平臺呼叫http://A/user/auth/acquire介面,但是介面缺失Cookie;

。。。。

之前明明是好的!!!

排查

詳細檢視下請求

發現了一個感嘆號,檢視內容,發現了SameSite屬性,且是因為SameSite=Lax導致無法set-cookie, 通過查詢瞭解一下這個屬性;可以看到阮大大的部落格有介紹這個屬性;

http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

以下摘自部落格:


Cookie 的SameSite屬性用來限制第三方 Cookie,從而減少安全風險。

它可以設定三個值。

  • Strict
  • Lax
  • None

2.1 Strict

Strict最為嚴格,完全禁止第三方 Cookie,跨站點時,任何情況下都不會發送 Cookie。換言之,只有當前網頁的 URL 與請求目標一致,才會帶上 Cookie。

Set-Cookie: CookieName=CookieValue; SameSite=Strict;

這個規則過於嚴格,可能造成非常不好的使用者體驗。比如,當前網頁有一個 GitHub 連結,使用者點選跳轉就不會帶有 GitHub 的 Cookie,跳轉過去總是未登陸狀態。

2.2 Lax

Lax規則稍稍放寬,大多數情況也是不傳送第三方 Cookie,但是導航到目標網址的 Get 請求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax;

導航到目標網址的 GET 請求,只包括三種情況:連結,預載入請求,GET 表單。詳見下表。

請求型別 示例 正常情況 Lax
連結 <a href="..."></a> 傳送 Cookie 傳送 Cookie
預載入 <link rel="prerender" href="..."/> 傳送 Cookie 傳送 Cookie
GET 表單 <form method="GET" action="..."> 傳送 Cookie 傳送 Cookie
POST 表單 <form method="POST" action="..."> 傳送 Cookie 不傳送
iframe <iframe src="..."></iframe> 傳送 Cookie 不傳送
AJAX $.get("...") 傳送 Cookie 不傳送
Image <img src="..."> 傳送 Cookie 不傳送

設定了StrictLax以後,基本就杜絕了 CSRF 攻擊。當然,前提是使用者瀏覽器支援 SameSite 屬性。

2.3 None

Chrome 計劃將Lax變為預設設定。這時,網站可以選擇顯式關閉SameSite屬性,將其設為None。不過,前提是必須同時設定Secure屬性(Cookie 只能通過 HTTPS 協議傳送),否則無效。

下面的設定無效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的設定有效。

Set-Cookie: widget_session=abc123; SameSite=None; Secure

很顯然,Chrome是支援SameSite屬性的,且通過資料可以知道在Chrome 80+版本,Chrome還將SameSite預設值改為了Lax,這也是導致此問題的主要原因;

以下是Chrome的特性介紹:

A cookie associated with a cross-site resource at accounts.google.com/ was set without the SameSite attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with SameSite=None and Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032

嘗試解決:

在Chrome啟動命令中,新增--disable-features=SameSiteByDefaultCookies命令,即可關閉SameSite屬性,此時問題修復;

步驟如下:

  1. 找到Chrome目錄,新建Chrome的快捷方式

  2. 右擊快捷方式的屬性,將屬性命令複製到目標欄中

  1. 儲存,關閉Chrome,然後通過新建的快捷方式開啟Chrome;

發現已經可以攜帶Cookie啦!

最後:

很顯然,我們不能要求客戶來幹這種事情。

所以結局是準備重新弄一下單點登入;