記SameSite屬性導致的跨域攜帶Cookie丟失
平臺一直使用一套騷操作來完成了單點登入,主要利用跨域cookie來獲取redis中快取的使用者資訊來判斷是否登入;突然有天失效了,於是有了此文;
平臺背景:
- 現有A、B兩個平臺,A登入後,將使用者登入資訊放入redis並獲取到key,將key存入http://A/user/的Cookie下;
- B平臺登入的時候跨域呼叫http://A/user/auth/acquire請求,此請求會攜帶這個域下的Cookie
- 後臺服務拿到Cookie中的key去reids查詢到登入資訊,返回登入成功;
- 完成整個的單點登入邏輯;
翻車現場:
- 測試提出單點登入失效,在A平臺登入成功後,訪問B平臺仍然需要登入;
於是開始排查:
- 檢視A平臺登入後,http://A/user/的Cookie下存在key, 此處沒有問題;
- 訪問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 | 不傳送 |
設定了Strict
或Lax
以後,基本就杜絕了 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
andhttps://www.chromestatus.com/feature/5633521622188032
嘗試解決:
在Chrome啟動命令中,新增--disable-features=SameSiteByDefaultCookies命令,即可關閉SameSite屬性,此時問題修復;
步驟如下:
-
找到Chrome目錄,新建Chrome的快捷方式
-
右擊快捷方式的屬性,將屬性命令複製到目標欄中
- 儲存,關閉Chrome,然後通過新建的快捷方式開啟Chrome;
發現已經可以攜帶Cookie啦!
最後:
很顯然,我們不能要求客戶來幹這種事情。
所以結局是準備重新弄一下單點登入;