SameSite Cookie 和 Same Origin Policy 是什麼
一般我們使用 Ajax 很長遇到跨域問題,之前我們很長設定 CORS
後端坐跨域設定結束這一回合。最近有研究 SSO 登入,有關 cookies 在不同子網域能不能做到 cookies 問題,原本覺得 cookies 是走 origin 的。結果後來發現 cookies 是走 SameSite ,我這邊就馬上惡補一下。結果發現有些東西很重要,但我竟然不知道,這邊簡單筆記一下。不過大致上你沒有要做到跨子網域登入一些東西可能就用不太到。
推薦文章
-
忍術!把 same site 變 same origin 之術! - Huli 備份圖
裡面寫滿多重點,文章範例比較攏長,不過幾乎規則都有提到。 -
SameSite小识 - 知乎 備份圖
上面文章看完可以看範例,比較能了解在講什麼
以上筆記從上面內容自己參考,真的上面內容都很完整,這邊簡單紀錄重點讓我方便回來複習。
小記
單字名詞意思
https://tw.yahoo.com:443
scheme
scheme 中文翻譯叫 方案
。可參考scheme - Yahoo奇摩字典 搜尋結果
簡單就是https://tw.yahoo.com:443
裡面的https
。
常見的 https
,http
,ftp
都是。
port
中文叫通訊協定,不過通常翻譯叫馬頭(港口)。
簡單就是https://tw.yahoo.com:443
裡面的443
。
host
中間那一串就是tw.yahoo.com
。
registrable domain
。Same Origin 是指完整子網域。這邊在比對上一開始也是看不懂,下面有提到eTLD
,相關去看如何判斷兩個網域的擁有者是否相同? | 半熟前端了解規則就容易了解差異。SameSite Cookie
SameSite 很多網站都說
scheme + host
。不看 port。這邊很多網站沒有細提 host 這邊指的是
registrable domain
。xxxx.com.tw
之類的沒有想到是跟
eTLD
有關係。可以看 如何判斷兩個網域的擁有者是否相同? | 半熟前端 備份圖
網域的運作機制對於前端最大的意義在於 SameSite2 的判斷,我們想要知道兩個網站是否為 SameSite,因為在 SameSite 的情況下網站的 Cookie 是共享的(在沒有特別設定 header 的情況下)。
因此給定兩個網站 URL,kalan.hacker.com 跟 jack.hacker.com,請問這兩個 URL 是否為 SameSite?乍看之下兩個 URL 很像 hacker.com 的 subdomain,但看完剛剛的例子與說明,我們應該先看看 hacker.com 有沒有在 public suffix list 裡才能做判斷。
在 GitHub 當中,可以透過 Repository 的設定免費生成 xxx.github.io 的網域 ,像是我的舊部落格: kjj6198.github.io/blog 。在這種情況下,我們可不希望每個 xxx.github.io 的 cookie 都可以互相存取。對於這類型的應用來說,我們希望的是每個 xxx.github.io 都是一個獨立的網域,而不是 .github.io 的子網域,透過 eTLD 可以有效解決這個問題,查看 public suffix list 也確實可以找到 .github.io 的存在
其實看到這邊就還蠻驚訝的!!我用電腦這麼久都不知道有這麼有趣機制XD
這邊其實不是重點,我就不繼續興奮討論。
這邊看SameSite小識 - 知乎實戰
我們假設有一個名字為sessionId的cookie,domain 設置成了 .demo.com。
- 在 a.demo.com 域名下,ajax在該域名下的所有請求,都會自動帶上sessionId。
ajax.get(’/api/data’) // 自動帶上sessionId- 在b.demo.com域名下,ajax在該域名下的所有請求,都會自動帶上sessionId。
ajax.post(’/api2/data2’) // 自動帶上sessionId- 在b.demo.com域名下,ajax請求a.demo.com的api,需要設置withCredentials才能帶上sessionId
ajax.get(‘https://a.demo.com/api/data') // 不能自動帶上sessionId
ajax.get(‘https://a.demo.com/api/data', {withCredentials: true}) // 自動帶上sessionId
這邊我們可以看到在 request 訪問 a.demo.com
和 b.demo.com
都會傳送 主網域.demo.com
cookies 資料。
瀏覽器 Demo
我直接用 Yahoo 新聞來看。開發者工具可以看到網站有用那些 cookies下圖。
在訪問https://tw.news.yahoo.com
會帶相關 cookies
但是在訪問非 https://tw.news.yahoo.com
網域 thamba
因 domain 設定在 https://tw.news.yahoo.com
,不會送出這組 cookies。參考下圖,我使用隨便不同子網域,並不回帶入thamba
cookies。下面改成用Firefox,因為Chrome 404不會顯示傳什麼 cookies。
注意整體 cookies 並非一致設定,可以個別設定。
上面不是有提到 registrable domain
是使用 eTLD
關係查到。
Firefox 和 Edge 可以看出 registrable domain
。
我們寫 cookies 進去通常有一個 domain
欄位,通常都不會帶。但瀏覽器不會隨便給你亂設定網域,這邊他會寫eTLD
,除非你有寫正確子網域。我以前都不知道為什麼沒法修改 domain ,現在知道為什麼了。
可能忽略 Cookies 跨域設定
參考: SameSite小識 - 知乎
我們常常前端串後端,因後端不同網域通常會後端加
|
|
但我們很少探討前端要怎麼跨域傳 cookies ,這邊還是傳送 SameSite喔
|
|
SameSite 規則設定
SameSite可以有下面三種值:
Strict僅允許一方請求攜帶Cookie,即瀏覽器將只發送相同站點請求的Cookie,即當前網頁URL與請求目標URL完全一致。
Lax允許部分第三方請求攜帶Cookie
None無論是否跨站都會發送Cookie
通常程式沒指定,預設都是Lax
。
Strict
只在 First-party 環境下帶上 Cookie,但這有個問題,假設使用者在 example.com 看到一條 FB 貼文連結(假設為 fb.com),就算使用者曾經登入過 fb.com 取得了 Cookie,點擊連結後因為兩個網站為 Cross-site,不會帶上 Cookie,只能看到登入頁面。因此 Strict 適合用在操作,例如刪除貼文、付款等等。
參考:[Day 26] Cookies - SameSite Attribute - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
這邊簡單想就是從外站(包含子網域)連到主網站 cookies 會不會帶入問題,這邊我還沒實驗。但看到上面探討 CORS 安全性問題大概應該是這樣,目前還沒想到簡易實作。這邊我有簡單做個實作測試,可以參考簡單實作測試 SameSite 的規則(Lax,Strict,None) - 程式狂想筆記。
跨域傳 cookies 需要 https
SameSite=Strict:最嚴謹,只有與目前網頁網址一致才能發送 (remote.example、site.example 互相無法發送)
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
SameSite=Lax:使用 GET remote.example 向 site.example 發送,Cookie 將會送向 remote.example (POST 則不會發送 Cookie)
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
SameSite=None + HTTPS:允許跨網域存取,但是若沒 HTTPS 則預設「拒絕」跨網域存取
無效:Set-Cookie: remote_session=abc123; SameSite=None
有效:Set-Cookie: remote_session=abc123; SameSite=None; Secure
參考:PHP Cookie SameSite 的設定方式 – Tsung’s Blog
我要測試 http 想說怎麼Lax
塞不進去,發現要 https
Same Origin Policy
建議可以看 簡單弄懂同源政策 (Same Origin Policy) 與跨網域 (CORS) | by Hannah Lin | Starbugs Weekly 星巴哥技術專欄 | Medium,因為這個我以前就很常遇到,所以就不仔細記錄。
檢查
- scheme
- host (跟samesite 不一樣的是不看
registrable domain
,是整個子網域) - port
比 SameSite 非常嚴格。
這邊簡單看 MDN給的判斷範例就一目瞭然。
這邊還是不知道差異嗎?這邊有比較可以參考
參考:忍術!把 same site 變 same origin 之術! - Huli’s blog