背景
Chrome瀏覽器升級到80以后铺坞,對屬性SameSite的默認值從None改為了Lax,從而導致我們的個別線上應用突然間拉胯了棒厘。
為什么該改動會影響線上系統(tǒng)呢檩互,在此得先描述一下受影響應用的特點:
三方系統(tǒng)引入,我們當時采用的Iframe方案蓖柔,也就是在系統(tǒng)A(a.xx.cn)中的頁面通過Iframe加載系統(tǒng)B(b.com.cn)辰企。
異常原因
經過分析后發(fā)現(xiàn),內嵌的系統(tǒng)B無法讀取自己設置的Cookie况鸣,導致一系列的問題牢贸。
是不是很奇怪,系統(tǒng)B自己設置的Cookie镐捧,自己讀不了十减。
Why?
在分析前愤估,首先我們得先了解一下帮辟,屬性SameSite的含義:
簡單來說,SameSite是響應頭的一個屬性玩焰,它的值會決定跨站訪問的時候是否允許發(fā)送Cookie由驹。SameSite的值有三個:Strict,Lax昔园,None蔓榄。
-
Strict:
最為嚴格,跨站訪問的時候默刚,完全不允許發(fā)送Cookie
-
Lax:
規(guī)則稍微放松甥郑,跨站訪問的時候,鏈接荤西,預加載請求澜搅,GET表單可以發(fā)送Cookie
-
None:
不限制伍俘,跨站訪問的時候都可以發(fā)送Cookie
請注意,我們在描述的時候勉躺,一直都加前綴“跨站訪問的時候”癌瘾,那什么是跨站?很多人會和跨域混淆饵溅,它倆在定義上是不同的妨退。
-
跨域:
非簡單請求,如果和請求目標在協(xié)議蜕企,域名咬荷,端口有一個不一樣,就認為是跨域轻掩。
-
跨站:
如果兩個站點萍丐,公共后綴(public suffix list)里的域名相同,并且再上一級也相同放典,就認為是同站逝变。反之就是跨站。
公共后綴(public suffix list)
是一份頂級域名列表奋构,最早是由Mozilla提出壳影,目前已經被主流瀏覽器采用。
舉個例子方便大家了解弥臼,下面兩個站點:a.teld.cn宴咧,b.teld.cn
是跨域么?很明顯径缅,是跨域掺栅,因為域名不同。
是跨站么纳猪?我們根據規(guī)則來看氧卧,公共后綴列表里,注冊的頂級域名是cn氏堤,cn前面一級是teld沙绝,都相同,所以不是跨站鼠锈。公共后綴有一份列表闪檬,大家可以自行搜索查看。
好购笆,目前為止粗悯,我們已經弄清楚跨域和跨站的區(qū)別。而屬性SameSite只是影響跨站訪問的情況同欠。我們再回過頭看第一句話“Chrome瀏覽器升級到80以后样傍,對屬性SameSite的默認值從None改為了Lax”
那80版本以前是什么樣呢横缔?
80以前,SameSite的默認值是None铭乾,也就是說我們在跨站訪問的時候剪廉,都可以發(fā)送Cookie娃循。下面舉個例子(聚焦前后端分離的場景炕檩,服務端寫Cookie,暫時忽略):
document.cookie = "test=1; Max-Age=2600000; "
80以前跨站的時候捌斧,寫讀很正常笛质。但80以后呢,SameSite的默認值改為了Lax捞蚂,那跨站的時候妇押,自然就讀不到了。
怎么解姓迅?第一想法就是把默認值設置成None(80以上版本要求設置None的時候敲霍,必須設置Secure)
document.cookie = "test=1; Max-Age=2600000; SameSite=None; Secure"
80以上版本是解決了,哪80版本以下呢丁存?這就不得不說一下兼容性問題肩杈,下面是谷歌的升級說明(點擊放大查看):
簡單來說就是:早期的版本并不能正確識別None,而且各個系統(tǒng)瀏覽器的行為還不一致解寝,有的會將SameSite=None的Cookie直接拒絕扩然,而有的就會解釋為SameSite=Strict,和我們的期望大相徑庭聋伦。
怎么解夫偶?目前通用的方案是多設置一個Cookie,如果Cookie讀寫方法封裝起來的話觉增,該操作對業(yè)務也是無感的兵拢,示例如下:
document.cookie = "test=1; Max-Age=2600000; SameSite=None; Secure"
多設置一個,當讀取的時候逾礁,先讀test卵佛,如果發(fā)現(xiàn)沒有再讀__test。
還有一種方案是通過UA檢測敞斋,進行瀏覽器黑名單的確認然后針對性處理截汪。雖然雙Cookie在資源上有浪費,但考慮到國內紛繁復雜的瀏覽器環(huán)境植捎,個人更推薦雙Cookie的解決方案衙解。
到這里問題結束了么?
如果系統(tǒng)是Windows焰枢,問題結束了
如果系統(tǒng)是Android蚓峦,問題結束了
如果系統(tǒng)是IOS或iPadOS舌剂,并且使用的Safari,那么尷尬依舊存在
因為從iOS 和 iPadOS 13.4 開始暑椰,Safari增加了智能反追蹤功能霍转,如圖:
并且“阻止跨網站跟蹤”默認是開啟的,意思就是拒絕所有的跨站請求傳送Cookie一汽,可以理解為設置SameSite=Strict避消,所以如果是ToC系統(tǒng),要考慮蘋果Safari用戶的話召夹,上述處理都有瑕疵岩喷。
總結
所以,跨站問題要處理到什么程度监憎,要結合自身系統(tǒng)特點來判斷纱意。比如:
網站并不依賴Cookie,那么恭喜你鲸阔,跨站對你沒任何影響偷霉。
少量依賴,看看是否可以考慮PostMessage的方式
內部系統(tǒng)的話是否可以限制瀏覽器版本
通過Nginx層面的域名處理褐筛,把跨站變?yōu)榉强缯?/p>
技術沒有銀彈类少,只要我們深入了解跨站請求的機制和原理,在合適的場景采用合適的技術策略死讹,跨站問題最終將迎刃而解瞒滴。