Cookie是什么?cookies是你訪問網站時創建的數據片段文件,
用來記錄訪問者的用戶信息、歷史記錄、訪問偏好、以及判定老訪客的登陸狀態,並且通過這些信息提升訪問者在網站上的使用體驗。
第一方Cookie vs 第三方Cookie
第一方cookie由你訪問的站點創建。該站點指的是地址欄顯示的站點;
第三方cookie是由其他站點創建的。這些站點擁有你當前訪問的網頁上部分資源,如廣告或圖像。
第一方/第三方cookie不是絕對的標簽,而是相對於用戶的上下文,同一cookie可以是第一方也可以是第三方,這取決於用戶當時所在的網站。
為什么要提第三方cookie,這與下面的cookie的SameSite策略密切相關。
cookie的常規使用方式
web服務端發送給瀏覽器的cookie,瀏覽器會存儲並在下次請求原服務器的時候回發cookie。
回發以HTTP Response Set-Cookie
標頭來體現, 通知瀏覽器種植cookie;
HTTP/1.0 200 OK Content-type: text/html Set-Cookie: yummy_cookie=choco Set-Cookie: X-BAT-FullTicketId=TGT-969171-******; path=/; samesite=none; httponly [page content]
Request
Cookie
標頭攜帶(該請求允許攜帶的)cookies,
Cookie
標頭的內容是鍵值對(鍵值對才是具業務含義的cookie);同名cookie覆蓋原鍵值,不同名cookie會追加到鍵值對。
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: yummy_cookie=choco; X-BAT-FullTicketId=TGT-969171-******
除了服務端響應時使用Set-Cookie
標頭種植cookie,瀏覽器JavaScript也可以種植cookie。
Cookie的種植面積
Domain
和Path
屬性定義了cookie的寫入范圍:哪些url的請求可以攜帶該cookie。
Domain
指定哪些host能被種植該cookie,如果沒有指定,默認是當前document location所在的host,不包含子域;- 如果指定了Domain,那么包括子域(也就是說在該域名下共享cookie,這也是利用二級域名共享cookie實現單點登錄的原理)。
例如設置了Domain=bat.com, 那么類似於developer.bat.com、xxoo.bat.com等子域下的url請求均會種下該cookie.
- Path 指定能攜帶該cookie的具體url。 "/" 是目錄分隔符,會匹配子目錄.
例如設置了Path =/doc,下面的目錄都會被匹配. - /docs - /docs/web/
- /docs/web/http
Cookie的有效時長
一般情況下瀏覽器關閉,cookie失效;
可通過設置特定的Expires或者Max-Age為cookie設置相對較長的有效時間。
Set-Cookie: id= a2faw; Expires=Wed,21 Oct 2015 07:12 GMT
當設置了過期時間,這個設置的時間是相對於瀏覽器而言,而非服務器。
Cookie與web安全息息相關
因為cookie是站點私有片段數據,與web上各種攻擊密切相關,如XSS,CSRF.
根據W3c的操作規范,種植cookie時可通過某些屬性限制cookie的使用方式。
發送Cookie的物理安全
Secure
指定了發送cookie的物理安全:要求以HTTPS形式回發cookie。 Chrome52+、Firefox52+已經支持Secure指令,再使用http請求已經不會自動攜帶Secure屬性的cookie
。
即便是Secure指令, 敏感信息也不要放在cookie中, 因為他們天生就不安全,https並不能提供足夠有效的安全防護。
誰能訪問Cookie?
web上能訪問cookie的物件有兩種:
-
瀏覽器請求
-
JavaScript
HttpOnly
指示cookie將不能通過JavaScript的document.cookie
編程接口訪問,這樣可以緩解對跨站點腳本(XSS
)的攻擊。
如:訪問會話在瀏覽器留置的認證cookie就沒有必要暴露給JavaScript,可對其設置HttpOnly指令 Set-Cookie: X-BAT-FullTicketId=TGT-969171-******; Expires=Wed, 21 Oct 2020 07:28:00 GMT; Secure; HttpOnly
哪些瀏覽器請求能合法攜帶Cookie?
首先科普一下重要的web HTTP知識:
對頁面資源的請求,依據請求發起者的源Origin與資源的源Origin的相等關系,被划分為4類。
Http請求中Sec-Fetch-Site
標頭指示了這個屬性, 這個標頭的值有瀏覽器自己判斷。
Sec-Fetch-Site | 描述 |
---|---|
cross-site | 請求的發起源與資源源完全不相同 |
same-origin | 請求的發起源與資源源完全相同 |
same-site | 請求的發起源與資源源部分相同:同一頂級域名下的二級域名 |
none |
注意, Sec-Fetch-** 標頭只會在 請求目標地址是 Https時,才會出現。
Q1. 域Domain、源Origin、站Site、傻傻分不清清楚?
觀察www.cnblog.com任意一篇博文的network,看動圖!
本人之前也被各種 域Domain、源Origin、站Site專屬名稱搞得很困惑?
在博客頁面
www.cnblog.com/xxx/p/110.htm
上發起的
www.cnblogs.com/xxx/ajax/Follow/GetFollowStatus.aspx
是same-origin請求
blog-static.cnblogs.com/files/shwee/clock.js
是same-site請求
www.google-analytics.com/r/collect?v=1&_v=j81&a=38982783&t=pageview&_s=1
是cross-site請求
Q2. 聊cookie為什么要提到給請求分類的Sec-Fetch-Site
標頭?
答:B站頁面在請求A站資源時能否攜帶A站cookie(第三方cookie
)不僅是一個道德問題;技術上還牽涉web安全(CSRF)。
針對以上的請求類型,瀏覽器針對cookie有SameSite
屬性,提供針對跨站點請求偽造攻擊(CSRF
)的保護。
在服務端Set-Cookie
種植cookie時,SmmeSite
屬性值可指示瀏覽器是否可在后續的“同一站點”或“跨站點”請求中攜帶這些cookie
Set-Cookie: X-bat-FullTicketId=TGT-178876-em4xx0faD1c4pbt*********k5Z0vN4uPOoEBWfGIP6l-bat-xxxxooo; path=/; samesite=none; httponly
有如下枚舉值:
-
Lax : 對同源、頂級域的請求才可以攜帶cookie (等價於same-site)
-
Strict: 對同源請求才可以使攜帶cookie (等價於same-origin)
-
None: 對於cookie的使用無限制,隨便使用
最新的IEEF cookie SameSite策略:
1. 敦促瀏覽器版本遷移,使cookie的SameSite默認= Lax(如果沒有設置SameSite屬性,這個SameSite就默認是Lax)
2. 如果需要跨域發送cookie,請使用None枚舉值選擇
無SameSite限制
, None指令需要搭配Secure
指令 (如果使用SameSite=None, 但是不帶secure,那么這個cookie將被丟棄 )
總之,IEEF配合瀏覽器給cookie的存取、傳輸規定了一套完整的策略,環環相扣,促進了web上cookie的平衡應用。
總結輸出
-
第一方cookie vs 第三方cookie的認定: 取決於訪客所處的上下文
-
cookie的常規用法,大家耳熟能詳
-
根據源Origin、站Site、域Domain,請求被划分為4大類,關注HTTP
Sec-Fetch-Site
標頭 -
服務器在種植cookie時,可對cookie設置SameSite屬性,故SameSite作用對象是cookie
-
SameSite屬性決定了后續的跨域/跨站請求是否可以攜帶B站cookie,緩解了CSRF攻擊
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
-
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Site
-
https://web.dev/samesite-cookies-explained