簡單的基於 cookie 的會話中介軟體。
使用者會話可以透過兩種主要方式儲存在 cookie 中:在伺服器或在用戶端。此模組會將會話資料儲存在用戶端的 cookie 中,而像 express-session 這樣的模組只會將會話識別碼儲存在用戶端的 cookie 中,並將會話資料儲存在伺服器中,通常是在資料庫中。
以下幾點可以協助您選擇要使用哪一種
cookie-session
不需要伺服器端的任何資料庫/資源,儘管總的會話資料不能超過瀏覽器的最大 cookie 大小。cookie-session
可以簡化某些負載平衡的場景。cookie-session
可用於儲存「輕量級」會話,並包含一個識別碼來查詢資料庫備份的次要儲存,以減少資料庫查詢。注意 此模組不會加密 cookie 中的會話內容,只提供簽署以防止篡改。用戶端將能夠透過檢查 cookie 的值來讀取會話資料。不應在未加密的情況下將機密資料設定在 req.session
中,或改用伺服器端的會話。
注意 此模組不會防止會話重播,因為過期設定僅適用於 cookie;如果這是你的應用程式的問題,你可以將過期日期儲存在 req.session
物件中,並在伺服器上驗證它,並實作任何其他邏輯來根據應用程式的需要延伸會話。
這是透過 npm 註冊 提供的 Node.js 模組。安裝是使用 npm install
指令 進行的
$ npm install cookie-session
var cookieSession = require('cookie-session')
var express = require('express')
var app = express()
app.use(cookieSession({
name: 'session',
keys: [/* secret keys */],
// Cookie Options
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}))
使用提供的選項建立新的 cookie 會話中介軟體。此中介軟體會將屬性 session
附加到 req
,它提供一個代表已載入會話的物件。如果請求中未提供有效的會話,則此會話是一個新的會話,否則會從請求中載入會話。
如果 req.session
的內容被變更,中介軟體會自動將 Set-Cookie
標頭新增到回應。注意,除非會話中有內容,否則回應中不會有 Set-Cookie
標頭(因此不會為特定使用者建立會話),因此務必在取得要為會話儲存的識別資訊後,將一些內容新增到 req.session
。
Cookie 會話接受選項物件中的這些屬性。
要設定的 Cookie 名稱,預設為 session
。
用於簽署和驗證 Cookie 值的金鑰清單,或已設定的 Keygrip
實例。設定的 Cookie 始終使用 keys[0]
簽署,而其他金鑰則可用於驗證,允許金鑰輪替。如果提供 Keygrip
實例,則可用於變更簽章參數,例如簽章演算法。
如果未提供 keys
,將使用此字串作為單一金鑰。
其他選項傳遞給 cookies.get()
和 cookies.set()
,允許您控制安全性、網域、路徑和簽署等設定。
選項也可以包含下列任一選項(完整清單,請參閱 cookies 模組文件
maxAge
:表示從 Date.now()
開始到過期的毫秒數expires
:表示 Cookie 過期日期的 Date
物件(預設在會話結束時過期)。path
:表示 Cookie 路徑的字串(預設為 /
)。domain
:表示 Cookie 網域的字串(沒有預設值)。sameSite
:表示 Cookie 是否為「同站」Cookie 的布林值或字串(預設為 false
)。這可以設定為 'strict'
、'lax'
、'none'
或 true
(對應到 'strict'
)。secure
:表示 Cookie 是否僅透過 HTTPS 傳送的布林值(HTTP 預設為 false
,HTTPS 預設為 true
)。如果這設定為 true
,而 Node.js 並未直接透過 TLS 連線,務必閱讀如何 在代理伺服器後方設定 Express,否則 Cookie 可能永遠無法正確設定。httpOnly
:表示 Cookie 是否僅透過 HTTP(S) 傳送,且不提供給用戶端 JavaScript(預設為 true
)。signed
:布林值,表示是否對 Cookie 進行簽署(預設為 true
)。overwrite
:布林值,表示是否覆寫先前設定的相同名稱 Cookie(預設為 true
)。表示給定要求的階段。
如果在要求期間已變更階段,則為 true
。
如果階段是新的,則為 true
。
判斷階段是否已填充資料或為空。
表示目前要求的階段選項。這些選項是中介軟體建構時所提供選項的淺層複製,可以變更這些選項以變更每個要求的 Cookie 設定行為。
若要銷毀階段,只需將其設定為 null
。
req.session = null
由於階段的全部內容都保留在用戶端的 Cookie 中,因此透過在 Set-Cookie
回應標頭中寫入 Cookie,可以「儲存」階段。如果在將 Node.js 回應標頭寫入用戶端時對階段進行變更,且階段未被銷毀,則會自動執行此動作。
var cookieSession = require('cookie-session')
var express = require('express')
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2']
}))
app.get('/', function (req, res, next) {
// Update views
req.session.views = (req.session.views || 0) + 1
// Write response
res.end(req.session.views + ' views')
})
app.listen(3000)
var cookieSession = require('cookie-session')
var express = require('express')
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2']
}))
// This allows you to set req.session.maxAge to let certain sessions
// have a different value than the default.
app.use(function (req, res, next) {
req.sessionOptions.maxAge = req.session.maxAge || req.sessionOptions.maxAge
next()
})
// ... your logic here ...
如果階段內容未變更,此模組不會傳送 Set-Cookie
標頭。這表示若要延長用戶瀏覽器中階段的到期時間(例如回應用戶活動),則需要對階段進行某種修改。
var cookieSession = require('cookie-session')
var express = require('express')
var app = express()
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2']
}))
// Update a value in the cookie so that the set-cookie will be sent.
// Only changes every minute so that it's not sent with every request.
app.use(function (req, res, next) {
req.session.nowInMinutes = Math.floor(Date.now() / 60e3)
next()
})
// ... your logic here ...
此範例顯示如何建立自訂 Keygrip
實例作為 keys
選項,以提供金鑰和額外的簽署設定。
var cookieSession = require('cookie-session')
var express = require('express')
var Keygrip = require('keygrip')
var app = express()
app.use(cookieSession({
name: 'session',
keys: new Keygrip(['key1', 'key2'], 'SHA384', 'base64')
}))
// ... your logic here ...
由於整個會話物件編碼後儲存在 Cookie 中,因此有可能超過不同瀏覽器的最大 Cookie 大小限制。RFC6265 規範建議瀏覽器應該允許
每個 Cookie 至少 4096 位元組(以 Cookie 名稱、值和屬性的長度總和衡量)
實際上,這個限制在不同瀏覽器之間略有不同。請參閱此處的瀏覽器限制清單。根據經驗法則,每個網域不要超過 4093 位元組。
如果您的會話物件大到足以在編碼時超過瀏覽器限制,在大多數情況下,瀏覽器會拒絕儲存 Cookie。這將導致瀏覽器發出的後續要求:a) 沒有任何會話資訊,或 b) 使用小到不會超過 Cookie 限制的舊會話資訊。
如果您發現會話物件達到這些限制,最好考慮是否應該從伺服器上的資料庫載入會話中的資料,而不是在每次要求時傳輸到/從瀏覽器。或者轉移到替代會話策略