HTTP系列之:HTTP中的cookies
簡(jiǎn)介
如果小伙伴最近有訪問國(guó)外的一些標(biāo)準(zhǔn)網(wǎng)站的話,可能經(jīng)常會(huì)彈出一個(gè)對(duì)話框,說是本網(wǎng)站為了更好的體驗(yàn)和跟蹤,需要訪問你的cookies,問你同意不同意,對(duì)于這種比較文明的做法,我一般是點(diǎn)同意的。
但是轉(zhuǎn)頭一想,為什么訪問國(guó)內(nèi)的網(wǎng)站從來沒有彈出過這個(gè)提示呢?這是一個(gè)值得深思的問題,或許當(dāng)你看完這篇文章之后,就有了答案。
cookies的作用
那么cookies有什么作用呢?HTTP cookies就是服務(wù)器端發(fā)送給瀏覽器端的一小部分?jǐn)?shù)據(jù),瀏覽器接收到這個(gè)數(shù)據(jù)之后,可以存起來自己用,也可以在后續(xù)發(fā)送到server端進(jìn)行一些數(shù)據(jù)的校驗(yàn)。
通過在cookies中存儲(chǔ)一些有用的數(shù)據(jù),可以將無狀態(tài)的HTTP協(xié)議變成有狀態(tài)的session連接,或者用來保存登錄的權(quán)限,下次不用密碼即可登陸,非常有用。
一般來說,cookies用在三個(gè)方面:
session的管理,用來保存登錄狀態(tài),從而讓HTTP請(qǐng)求可以帶上狀態(tài)信息。
用戶自定義的設(shè)置,這些用戶特殊的字段,需要保存在cookies中。
跟蹤用戶的行為信息。
在很久很久以前,還沒有現(xiàn)代瀏覽器的時(shí)候,客戶端的唯一存儲(chǔ)就是cookies,所以cookies也作為客戶端存儲(chǔ)來使用的,但是有了現(xiàn)代的瀏覽器之后,一般是建議把客戶端存儲(chǔ)的數(shù)據(jù)放到其他存儲(chǔ)方式中。
為什么呢?
因?yàn)槊看握?qǐng)求cookies中的數(shù)據(jù)會(huì)自動(dòng)帶上,并且發(fā)送到server端,所以如果cookies中存儲(chǔ)了太多的數(shù)據(jù),就會(huì)導(dǎo)致服務(wù)器性能的下降。
創(chuàng)建cookies
因?yàn)閏ookies是客戶端的本地存儲(chǔ),所以如果服務(wù)器端想要設(shè)置客戶端的cookies時(shí),通過在響應(yīng)頭中設(shè)置Set-Cookie,瀏覽器接收到這個(gè)響應(yīng)頭之后,就會(huì)將對(duì)應(yīng)的cookies內(nèi)容存儲(chǔ)到瀏覽器本地。
然后在后續(xù)的服務(wù)器請(qǐng)求中都會(huì)帶上Cookie header。同時(shí)cookie還可以帶上過期時(shí)間、發(fā)送限制等屬性。
先來看下Set-Cookie的格式:
Set-Cookie: <cookie-name>=<cookie-value>
復(fù)制代碼舉個(gè)例子,下面是一個(gè)server端的響應(yīng):
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: name=flydean
Set-Cookie: site=www.flydean.com
復(fù)制代碼當(dāng)瀏覽器接收到這個(gè)響應(yīng)之后,就會(huì)在本地的cookies中設(shè)置對(duì)應(yīng)的值,并且在后續(xù)的請(qǐng)求中將這些值以cookies的header形式帶上:
GET /test.html HTTP/2.0
Host: www.flydean.com
Cookie: name=flydean; site=www.flydean.com
復(fù)制代碼在netty中提供了一個(gè)Cookie的類,專門用來表示cookies,這個(gè)類中提供了cookies的基本屬性,然后通過使用:
response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie));
復(fù)制代碼來對(duì)響應(yīng)頭進(jìn)行設(shè)置。
cookies的生存時(shí)間
HTTP的cookies有兩種,一種是session cookies,這種cookies會(huì)在session結(jié)束之后自行刪除。
還有一種cookies通過指定Expires或者 Max-Age 來設(shè)置過期時(shí)間:
Set-Cookie: id=abcdef; Expires=Thu, 31 May 2021 08:00:00 GMT;
復(fù)制代碼其中Expires是HTTP1.0中定義的header,Max-Age是HTTP1.1中定義的header。
cookies的權(quán)限控制
HTTP提供了兩個(gè)屬性來對(duì)cookies的權(quán)限進(jìn)行控制,分別是Secure和HttpOnly。
如果cookies中帶有Secure屬性,那么cookies只會(huì)在使用HTTPS協(xié)議的時(shí)候發(fā)送給服務(wù)器。如果使用的是HTTP協(xié)議,則不會(huì)發(fā)送cookies信息。
并且,如果是在http的情況下,server端是不允許給cookie設(shè)置Secure屬性的。
但是設(shè)置了Secure屬性并不意味著cookies就是安全的,因?yàn)榭梢詮钠渌氖侄文玫綖g覽器端的cookies。
還有一個(gè)屬性是HttpOnly,如果cookies設(shè)置了HttpOnly,那么cookies是不允許被JavaScript訪問的,通過設(shè)置HttpOnly,我們可以提升客戶端數(shù)據(jù)的安全性:
Set-Cookie: id=abcdef; Expires=Thu, 21 May 2021 08:00:00 GMT; Secure; HttpOnly
復(fù)制代碼cookies還可以添加Domain和Path屬性,用于標(biāo)記cookies可以發(fā)送到的URL。
其中Domain表示域名,而Path表示路徑。
如果Domain沒有設(shè)置,則默認(rèn)是設(shè)置cookies的host,這個(gè)host是不包含子domain的。如果手動(dòng)指定了Domain,那么子domain是會(huì)包含在內(nèi)的。
比如如果我們?cè)O(shè)置了Domain=flydean.com,那么子domain:doc.flydean.com也會(huì)共享這個(gè)cookies。
Path用來匹配URL的路徑,只有匹配到的URL才可以發(fā)送cookies。
另外HTTP還提供了一個(gè)SameSite屬性,表示如果是在CORS環(huán)境情況下,是否發(fā)送cookies到第三方網(wǎng)站,這樣可以在一定程度上保護(hù)網(wǎng)站的信息。
SameSite有三個(gè)可能的值,分別是Strict, Lax, 和 None。如果在Strict情況下,那么cookie僅發(fā)送到與創(chuàng)建它的站點(diǎn)相同的站點(diǎn)。Lax跟Strict類似,不同之處在于當(dāng)用戶導(dǎo)航到cookie的原始站點(diǎn)時(shí)發(fā)送cookie,比如通過訪問外部站點(diǎn)的鏈接。None可以在原始網(wǎng)站和跨站資源訪問中使用,但是必須要在安全的環(huán)境中進(jìn)行(設(shè)置Secure屬性)。如果沒有設(shè)置SameSite,那么表現(xiàn)是和Lax一致的。
例如:
Set-Cookie: name=flydean; SameSite=Strict
復(fù)制代碼第三方cookies
我們知道cookies是和domain相關(guān)的,如果cookies的domain是和當(dāng)前訪問的頁(yè)面相同的話,這個(gè)cookies就叫做 first-party cookies。如果和當(dāng)前的訪問頁(yè)面不同,比如訪問第三方的圖片、腳本、css等,第三方的服務(wù)器有可能會(huì)發(fā)送他們自己的cookies,這種cookies叫做第三方cookies,第三方cookies主要被用來廣告或者跟蹤用戶的行為信息。
對(duì)于有些瀏覽器來說,可能會(huì)禁用第三方的cookies,這有可能會(huì)導(dǎo)致訪問網(wǎng)站的一些功能問題,大家可以主要觀察一下。
總結(jié)
使用cookies可以輔助我們做很多事情,但是也要注意cookies的安全性。
作者:程序那些事
鏈接:https://juejin.cn/post/7001712204512919559
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
