Chrome升級后禁用三方Cookie,理解Cookie的SameSite新屬性!
作者:港式豉汁蒸魚
原文:https://juejin.cn/post/7008455334830276644
前言
年初,我們小組在對接操作員中心時遇到了這樣一個問題:登錄成功后Cookie無法傳遞導(dǎo)致登錄狀態(tài)失效。經(jīng)過排查發(fā)現(xiàn),當(dāng)服務(wù)端通過 Set-Cookie 響應(yīng)頭設(shè)置 Cookie 到客戶端時,Chrome瀏覽器發(fā)出警告:Cookie的SameSite默認為Lax,因此部分跨站請求將不攜帶此Cookie。

原來Google在2020年2月4號發(fā)布的 Chrome 80 版本,將沒有聲明SameSite值的cookie默認設(shè)置為SameSite=Lax,以此來減少非安全第三方 cookie 的使用。
初學(xué)者的我有了疑問:SameSite屬性是什么?Chrome為什么要這樣做?我們要如何應(yīng)對這一改變?帶著這些疑問跟著本文來深入理解SameSite。
CSRF攻擊
要了解SameSite屬性,那就不得不提到CSRF攻擊。
CSRF,全稱Cross-site request forgery,意為跨站請求偽造。是指一些惡意網(wǎng)站會誘導(dǎo)用戶向被攻擊網(wǎng)站發(fā)送跨站請求,利用用戶已獲得的登錄狀態(tài)繞過后臺的用戶驗證,達到冒充用戶對被攻擊的網(wǎng)站執(zhí)行某項操作的目的。
比如GET類型的CSRF攻擊非常簡單,只需要一個HTTP請求:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
復(fù)制代碼
之前用戶登錄了信任的網(wǎng)站A,并且保存登錄狀態(tài)。在他訪問含有這個img的惡意頁面后,瀏覽器會自動發(fā)出一次HTTP請求,bank.example就會收到包含用戶登錄信息的一次跨域請求,往黑客賬戶中轉(zhuǎn)賬1W元。
Cookie 往往用來存儲用戶的身份信息,作為瀏覽器和服務(wù)器之間維護登錄狀態(tài)的一個關(guān)鍵數(shù)據(jù)。而惡意網(wǎng)站正是利用了Cookie達到CSRF攻擊。
與當(dāng)前站點的域相匹配的 Cookie,即瀏覽器地址欄中顯示的內(nèi)容,被稱為第一方Cookie。同樣,來自當(dāng)前站點以外的域的 cookie 被稱為第三方cookie。第三方 Cookie除了被用于 CSRF 攻擊,還被用于用戶追蹤,成了各大廣告和購物網(wǎng)站窺探用戶隱私的利器。

因此,為了阻止不明外域的訪問、防止CSRF攻擊和用戶追蹤,從Chrome 51 開始,瀏覽器的 Cookie 新增加了一個SameSite屬性。
SameSite屬性
Cookie 的SameSite屬性的引入,將允許用戶指定是否將cookie限制為相同站點的請求。它可以設(shè)置三個值:
Strict 最為嚴(yán)格,完全禁止第三方 Cookie,只有當(dāng)前網(wǎng)頁 URL 與請求目標(biāo) URL 完全一致才會帶上Cookie。 Lax 允許部分第三方請求攜帶 Cookie,具體見下圖。 None 無論是否跨站都會發(fā)送 Cookie

這里需要理解 [同源/跨域] 和 [同站/跨站] 的區(qū)別。
瀏覽器同源策略(SOP)中的「同源(same-origin)]是指兩個 URL 的協(xié)議/主機名/端口一致。例如,www.baidu.com/pages/[1]...,它的協(xié)議是 https,主機名是www.baidu.com ,端口是 443。
同源策略作為瀏覽器的安全基石,其「同源」判斷是比較嚴(yán)格的,相對而言,Cookie中的「同站」判斷就比較寬松:只要兩個 URL 的 eTLD+1 相同即可,不需要考慮協(xié)議和端口。其中,eTLD 表示有效頂級域名,例如,.com、.co.uk、.github.io 等。eTLD+1 則表示,有效頂級域名+二級域名,例如 taobao.com 等。
舉幾個例子,www.baidu.com[2] 和 www.juejin.com[3] 是跨站,www.a.juejin.com 和 www.b.juejin.com[4] 是同站,www.a.juejin.com:80[5] 和 www.a.juejin.com:3000[6] 是跨域。
對于防范 CSRF 攻擊,我們可以針對實際情況將一些關(guān)鍵的 Cookie 設(shè)置為 Strict 或者 Lax 模式,這樣在跨站點請求時,這些關(guān)鍵的 Cookie 就不會被發(fā)送到服務(wù)器,從而使得黑客的 CSRF 攻擊失效。
雖然該SameSite屬性得到了廣泛的支持,但遺憾的是它并未被開發(fā)人員廣泛采用,依舊使用戶容易受到 CSRF 和無意信息泄露的影響。因此Chrome采取了開頭所說的SameSite默認策略,將沒有聲明SameSite值的cookie默認設(shè)置為SameSite=Lax。而這會讓一些使用第三方cookie場景的系統(tǒng),造成登陸異常、系統(tǒng)崩潰等大問題。
解決方案
SameSite默認策略造成的影響不可疏忽。有人提出修改客戶端瀏覽器設(shè)置,禁用“SameSite by default cookies”,簡單粗暴,但這只是個應(yīng)急方案,這違背了BS架構(gòu)應(yīng)用的最大優(yōu)點,開發(fā)者無法為所有客戶端安裝部署。那么開發(fā)者該如何應(yīng)對呢?以下淺陋地提出了幾種應(yīng)對方案。
Ngnix反向代理解決跨域問題
既然不支持三方cookie,那我們就解決跨域問題。本文不細說啦。
設(shè)置 SameSite 為 none
由服務(wù)端將response的header設(shè)置Set-Cookie:SameSite=None,允許跨站請求發(fā)送 Cookie。
不過有兩點需要特別注意:
HTTP 接口不支持 SameSite=none
如果你想加 SameSite=none 屬性,那么該 Cookie 就必須同時加上 Secure 屬性,表示只有在 HTTPS 協(xié)議下該 Cookie 才會被發(fā)送。這也意味著,你的網(wǎng)站需要向https遷移,這也讓你的網(wǎng)站更安全。
Set-cookie: key=value; SameSite=None; Secure
Set-cookie: key=value; Secure
復(fù)制代碼
需要 UA 檢測,部分瀏覽器不能加 SameSite=none
IOS 12 的 Safari 以及老版本的一些 Chrome 會錯把 SameSite=none 識別成 SameSite=Strict,所以服務(wù)端必須在下發(fā) Set-Cookie 響應(yīng)頭時進行 User-Agent 檢測來判斷是否加上SameSite=none。
Electron的useSessionCookies
但服務(wù)端修改響應(yīng)頭的方法并不適用于我們當(dāng)前場景,因為我們無法修改操作員中心接口。我們的產(chǎn)品FIP基于Electron,Electron基于 Node.js 和 Chromium,于是我們將目光轉(zhuǎn)向Electron,看看它是否有解決方案。
反復(fù)翻閱Electron官方文檔后發(fā)現(xiàn),Electron使用Chromium的原生網(wǎng)絡(luò)庫發(fā)出HTTP / HTTPS請求,其請求對象有以下兩個神秘的參數(shù):
session Object (可選) - 與請求相關(guān)聯(lián)的Session實例. useSessionCookies Boolean (可選) - 是否從提供的會話與請求一起發(fā)送cookie。
這個session實例負責(zé)管理瀏覽器會話、cookie等,當(dāng)服務(wù)端返回 Set-Cookie響應(yīng)頭時,Electron會將該 Cookie 存儲在與請求相關(guān)聯(lián)的Session實例中;當(dāng)useSessionCookies為true 時,在下次向服務(wù)器發(fā)送請求時,會攜帶上之前存儲的Session實例中的 Cookie。雖然這繞開了SameSite默認策略,但或許會帶來一些安全問題。
小結(jié)
本文介紹了sameSite屬性的產(chǎn)生背景和作用,介紹了Chrome80+ SameSite默認策略帶來的影響,最后淺陋地提出了幾種應(yīng)對方案。
雖然Chrome這一改變,讓開發(fā)者加了波班,但這也說明了Chrome對前端安全和用戶隱私的重視,鼓勵開發(fā)者主動為用戶提供更安全的體驗,而不是依賴于瀏覽器的默認行為。
參考
預(yù)測最近面試會考 Cookie 的 SameSite 屬性[7]
阮一峰-Cookie 的 SameSite 屬性[8]
參考資料
https://www.baidu.com/pages/: https://link.juejin.cn?target=https%3A%2F%2Fwww.baidu.com%2Fpages%2F
[2]http://www.baidu.com: https://link.juejin.cn?target=http%3A%2F%2Fwww.baidu.com
[3]http://www.juejin.com: https://link.juejin.cn?target=http%3A%2F%2Fwww.juejin.com
[4]http://www.b.juejin.com: https://link.juejin.cn?target=http%3A%2F%2Fwww.b.juejin.com
[5]http://www.a.juejin.com:80: https://link.juejin.cn?target=http%3A%2F%2Fwww.a.juejin.com%3A80
[6]http://www.a.juejin.com:3000: https://link.juejin.cn?target=http%3A%2F%2Fwww.a.juejin.com%3A3000
[7]https://juejin.cn/post/6844904095711494151: https://juejin.cn/post/6844904095711494151
[8]http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html: https://link.juejin.cn?target=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2019%2F09%2Fcookie-samesite.html
最后
如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)
歡迎加我微信「 sherlocked_93 」拉你進技術(shù)群,長期交流學(xué)習(xí)...
關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。

