黑人生命也是命。
支持平等正義倡議.

cookie-session

NPM Version NPM Downloads Build Status Test Coverage

簡單的基於 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

API

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
}))

cookieSession(options)

使用提供的選項建立新的 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)。

req.session

表示給定要求的階段。

.isChanged

如果在要求期間已變更階段,則為 true

.isNew

如果階段是新的,則為 true

.isPopulated

判斷階段是否已填充資料或為空。

req.sessionOptions

表示目前要求的階段選項。這些選項是中介軟體建構時所提供選項的淺層複製,可以變更這些選項以變更每個要求的 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 限制的舊會話資訊。

如果您發現會話物件達到這些限制,最好考慮是否應該從伺服器上的資料庫載入會話中的資料,而不是在每次要求時傳輸到/從瀏覽器。或者轉移到替代會話策略

授權

MIT