注意

本页面生成自 cookie-session README

cookie-session

NPM Version NPM Downloads Build Status Test Coverage

简单的基于 cookie 的会话中间件。

用户会话可以通过两种主要方式与 cookie 一起存储:在服务器上或在客户端上。此模块将会话数据存储在客户端的 cookie 中,而像 express-session 这样的模块只在客户端的 cookie 中存储会话标识符,并将会话数据存储在服务器上,通常在数据库中。

以下几点可以帮助您选择使用哪种方式:

注意 本模块不加密 cookie 中的会话内容,仅提供签名以防止篡改。客户端可以通过检查 cookie 的值来读取会话数据。未经加密的秘密数据不应设置在 req.session 中,或者应改用服务器端会话。

注意 本模块不阻止会话重放,因为设置的过期时间仅限于 cookie;如果您的应用程序关注此问题,您可以在 req.session 对象中存储一个过期日期并在服务器上验证它,并根据应用程序需要实现任何其他扩展会话的逻辑。

安装

这是一个通过 npm registry 提供的 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 附加到 reqreq 提供一个表示已加载会话的对象。如果请求中未提供有效的会话,则此会话是一个新会话;否则,它是从请求中加载的会话。

如果 req.session 的内容被修改,中间件将自动向响应添加一个 Set-Cookie 头部。请注意,除非会话中有内容,否则响应中不会有 Set-Cookie 头部(因此不会为特定用户创建会话),所以请务必在获得可存储用于会话的识别信息后,立即向 req.session 添加一些内容。

选项

Cookie 会话在选项对象中接受以下属性。

name

要设置的 cookie 名称,默认为 session

keys

用于签名和验证 cookie 值的键列表,或一个已配置的 Keygrip 实例。设置的 cookie 总是用 keys[0] 签名,而其他键则用于验证,从而允许密钥轮换。如果提供了 Keygrip 实例,它可用于更改签名参数,例如签名算法。

secret

如果未提供 keys,则用作单个键的字符串。

其他选项将传递给 cookies.get()cookies.set(),允许您控制安全性、域、路径和签名等设置。

选项还可以包含以下任何内容(完整列表请参阅 cookies 模块文档

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