簡介
如果小夥伴最近有訪問國外的一些標準網站的話,可能經常會彈出一個對話框,説是本網站為了更好的體驗和跟蹤,需要訪問你的cookies,問你同意不同意,對於這種比較文明的做法,我一般是點同意的。
但是轉頭一想,為什麼訪問國內的網站從來沒有彈出過這個提示呢?這是一個值得深思的問題,或許當你看完這篇文章之後,就有了答案。
cookies的作用
那麼cookies有什麼作用呢?HTTP cookies就是服務器端發送給瀏覽器端的一小部分數據,瀏覽器接收到這個數據之後,可以存起來自己用,也可以在後續發送到server端進行一些數據的校驗。
通過在cookies中存儲一些有用的數據,可以將無狀態的HTTP協議變成有狀態的session連接,或者用來保存登錄的權限,下次不用密碼即可登陸,非常有用。
一般來説,cookies用在三個方面:
- session的管理,用來保存登錄狀態,從而讓HTTP請求可以帶上狀態信息。
- 用户自定義的設置,這些用户特殊的字段,需要保存在cookies中。
- 跟蹤用户的行為信息。
在很久很久以前,還沒有現代瀏覽器的時候,客户端的唯一存儲就是cookies,所以cookies也作為客户端存儲來使用的,但是有了現代的瀏覽器之後,一般是建議把客户端存儲的數據放到其他存儲方式中。
為什麼呢?
因為每次請求cookies中的數據會自動帶上,並且發送到server端,所以如果cookies中存儲了太多的數據,就會導致服務器性能的下降。
創建cookies
因為cookies是客户端的本地存儲,所以如果服務器端想要設置客户端的cookies時,通過在響應頭中設置Set-Cookie,瀏覽器接收到這個響應頭之後,就會將對應的cookies內容存儲到瀏覽器本地。
然後在後續的服務器請求中都會帶上Cookie header。同時cookie還可以帶上過期時間、發送限制等屬性。
先來看下Set-Cookie的格式:
Set-Cookie: <cookie-name>=<cookie-value>
舉個例子,下面是一個server端的響應:
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: name=flydean
Set-Cookie: site=www.flydean.com
當瀏覽器接收到這個響應之後,就會在本地的cookies中設置對應的值,並且在後續的請求中將這些值以cookies的header形式帶上:
GET /test.html HTTP/2.0
Host: www.flydean.com
Cookie: name=flydean; site=www.flydean.com
在netty中提供了一個Cookie的類,專門用來表示cookies,這個類中提供了cookies的基本屬性,然後通過使用:
response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie));
來對響應頭進行設置。
cookies的生存時間
HTTP的cookies有兩種,一種是session cookies,這種cookies會在session結束之後自行刪除。
還有一種cookies通過指定Expires或者 Max-Age 來設置過期時間:
Set-Cookie: id=abcdef; Expires=Thu, 31 May 2021 08:00:00 GMT;
其中Expires是HTTP1.0中定義的header,Max-Age是HTTP1.1中定義的header。
cookies的權限控制
HTTP提供了兩個屬性來對cookies的權限進行控制,分別是Secure和HttpOnly。
如果cookies中帶有Secure屬性,那麼cookies只會在使用HTTPS協議的時候發送給服務器。如果使用的是HTTP協議,則不會發送cookies信息。
並且,如果是在http的情況下,server端是不允許給cookie設置Secure屬性的。
但是設置了Secure屬性並不意味着cookies就是安全的,因為可以從其他的手段拿到瀏覽器端的cookies。
還有一個屬性是HttpOnly,如果cookies設置了HttpOnly,那麼cookies是不允許被JavaScript訪問的,通過設置HttpOnly,我們可以提升客户端數據的安全性:
Set-Cookie: id=abcdef; Expires=Thu, 21 May 2021 08:00:00 GMT; Secure; HttpOnly
cookies還可以添加Domain和Path屬性,用於標記cookies可以發送到的URL。
其中Domain表示域名,而Path表示路徑。
如果Domain沒有設置,則默認是設置cookies的host,這個host是不包含子domain的。如果手動指定了Domain,那麼子domain是會包含在內的。
比如如果我們設置了Domain=flydean.com,那麼子domain:doc.flydean.com也會共享這個cookies。
Path用來匹配URL的路徑,只有匹配到的URL才可以發送cookies。
另外HTTP還提供了一個SameSite屬性,表示如果是在CORS環境情況下,是否發送cookies到第三方網站,這樣可以在一定程度上保護網站的信息。
SameSite有三個可能的值,分別是Strict, Lax, 和 None。如果在Strict情況下,那麼cookie僅發送到與創建它的站點相同的站點。Lax跟Strict類似,不同之處在於當用户導航到cookie的原始站點時發送cookie,比如通過訪問外部站點的鏈接。 None可以在原始網站和跨站資源訪問中使用,但是必須要在安全的環境中進行(設置Secure屬性)。如果沒有設置SameSite,那麼表現是和Lax一致的。
例如:
Set-Cookie: name=flydean; SameSite=Strict
第三方cookies
我們知道cookies是和domain相關的,如果cookies的domain是和當前訪問的頁面相同的話,這個cookies就叫做 first-party cookies。如果和當前的訪問頁面不同,比如訪問第三方的圖片、腳本、css等,第三方的服務器有可能會發送他們自己的cookies,這種cookies叫做第三方cookies,第三方cookies主要被用來廣告或者跟蹤用户的行為信息。
對於有些瀏覽器來説,可能會禁用第三方的cookies,這有可能會導致訪問網站的一些功能問題,大家可以主要觀察一下。
總結
使用cookies可以輔助我們做很多事情,但是也要注意cookies的安全性。
本文已收錄於 http://www.flydean.com/05-http-cookie/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!