[web] Session & Cookie
keywords: cookie
, session
Session 與 Cookie 的關係
- 白話 Session 與 Cookie:從經營雜貨店開始 @ Huli
- Session & Cookie @ AlphaCamp
- Get Ready for New SameSite=None; Secure Cookie Settings @ Google Developer
傳統上指稱的 Session 是存放在伺服器上的,Client 的 request 中帶著的 Cookie,這個 Cookie 內包 含 session_id 的訊息,server 便可以透過此 session_id 去查找伺服器上 Session 資料表內,找出該使用者的身份為何。
What is the difference between localStorage, sessionStorage, session and cookies? @ StackOverflow
Cookie
待參考:👍 HTTP Cookie
Set-Cookie:
cookieKey=cookieValue; # key-value pair
expires=Tue, 09 Jun 2020 15:46:52 GMT; # 過期時間
Max-Age=1209600; # 最常有效時間(優先權較高)
Path=/about/; # 只限定作用在某個 path,預設是 "/"
Domain=api.pjchender.com; # 只限定作用在某個 domain
Secure; # 只能在 HTTPS 的協定下傳送此 Cookie
HttpOnly; # 不能透過 Document.cookie 這種 JS 的方式讀取 Cookie
SameSite=Lax; # 包含 Lax, Strict, None,跨站情況下是否要傳送該 Cookie
Expires 和 Max-Age 的設定
- 當同時設定
expires
和Max-Age
時,Max-Age
有比較高的優先權。
Domain 的設定
- 當不在該 Domain 的環境下,卻針對其他 Domain 設定 Cookie 時會無效。舉例來說,在 pjchender.blogspot.com 中透過 Set-Cookie 試圖設定
Domain=pjchender.github.io
時,會沒有作用,瀏覽器會拒絕這個 Cookie。 - 一般的情況下,若設定
Domain=pjchender.com
那麼不論所處的 subdomain 為何(例如,info.pjchender.com, dev.pjchender.com)都可以成功設定此 Cookie。但當這個 domain 是列在 Public Suffix List 中時,會有例外的情況,以 github.io 為例,即使我在 pjchender.github.io 這個網域,但因為 github.io 是被列在 Public Suffix List 中,因此將不能設定Domain=github.io
,此 Cookie 設定會無效,並且被瀏覽器拒絕。
AJAX 請求
-
當 AJAX 發送請求的來源和目標 domain 相同時,瀏覽器會在請求中帶入目標 domain 的 credentials(即,Cookie)。
-
若來源和目標 domain 不同時,設定的情況下瀏覽器不會把 credentials(即,Cookie)添加到該請求中,除非在 AJAX 的請求中加上
credentials: "include"
的參數,例如:fetch('https://www.pjchender.com', {
credentials: 'include',
});同時在 server 的部分,若想要順利處理此請求,需要在 header 中給予
Access-Control-Allow-Credentials
和Access-Control-Allow-Origin
的設定。
Same-Site/First-Party or Cross-Site/Third-Party cookies
- Prepare for phasing out third-party cookies @ Google Developers > Privacy Sandbox
- Preparing for the end of third-party cookies @ Google Developers
每個 Cookie 都會有一個相關聯的 domain:
- Cross-site (Third Party):如果這個 domain 和使用者當前網址列上的 domain 不同
- Same-site(First Party):如果這個 domain 和使用者當前網址列上的 domain 相同
這幾年(2019、2020 年)如果想要使用 Third-Party Cookie,一定要使用 SameSite=None; Secure
,但因為 Third-Party Cookies 太常被用來追蹤使用者的 Profile,廣告商利用 Third-Party Cookie,做到 cross-site tracking,也就是廣告商能夠跨站辨別使用者的身分,進而得知使用者瀏覽了那些網站,進一步推測使用者的偏好。
為了提升使用者的隱私權,越來越多瀏覽器禁止使用 Third-Party Cookies,也就是說,即使加上了 SameSite=None
也沒有用。
Google Chrome 預計在 2024 年也開始禁用 Third-Party Cookie,取而代之的是提供了隱私權(可能)更好的幾種不同做法:
-
Partitioned with CHIPS (Cookies Having Independent Partitioned State):這個 Third Party 的 Cookie 只能讀寫在同一個 domain 下的內容,沒辦法跨站讀取,如此來避免 cross-site tracking。適合用在每一個 site 底下都是獨立不需相依辨認使用者的情況。
-
使用 CHIPS 時,需要搭配
SameSite=none; Secure
,缺少的話瀏覽器會自動忽略;另外很重要的是,如果要移除帶有 Partitioned 的 Cookie,SameSite
和Secure
也還是要加上:// Vanilla
document.cookie =
'Foo=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; partitioned; samesite: none; secure';// universal-cookie
cookies.set('Foo', 'bar', {
partitioned: true,
sameSite: 'none',
secure: true,
});
cookies.remove('Foo', {
partitioned: true,
sameSite: 'none',
secure: true,
});
-
-
Storage Access API:在使用 Third-Party Cookies 前,會先向使用者詢問是否提供權限
-
Related Website Sets (RWS):預先定義好一系列實際有關聯的網站(例如同一個集團底下的不同網站),並提交審核後,如此可以在不向使用者詢問權限的情況下,做到 cross-site tracking。
參考
- A practical, complete guide to HTTP cookies @ Valentino