会话 Session

导读

HTTP 会话 提供了一种跨多个请求存储用户信息的方法,这对于 MVC 应用程序特别有用。

与 Express 一起使用(默认)

首先安装 必需包(对于 TypeScript 用户,安装其类型):

shell
$ npm i express-session
$ npm i -D @types/express-session

安装完成后,将 express-session 中间件应用为全局中间件(例如,在您的 main.ts 文件中)。

ts
import * as session from 'express-session'
// somewhere in your initialization file
app.use(
  session({
    secret: 'my-secret',
    resave: false,
    saveUninitialized: false,
  }),
)
通知

默认的服务器端会话存储不是为生产环境设计的。在大多数情况下,它会泄漏内存,无法扩展到单个进程之外,并且仅用于调试和开发。在官方存储库 中阅读更多内容。

secret 用于签署会话 ID cookie。这可以是单个机密的字符串,也可以是多个机密的数组。如果提供了机密数组,则只有第一个元素将用于签署会话 ID cookie,而在验证请求中的签名时将考虑所有元素。机密本身不应被人类轻易解析,最好是一组随机字符。

启用 resave 选项会强制将会话保存回会话存储,即使在请求期间从未修改过会话。默认值为 true,但使用默认值已被弃用,因为默认值将来会发生变化。

同样,启用 saveUninitialized 选项会强制将未初始化的会话保存到存储中。会话在新建但未修改时未初始化。选择 false 有助于实现登录会话、减少服务器存储使用量或遵守在设置 cookie 之前需要获得许可的法律。选择 false 还有助于解决客户端在没有会话的情况下发出多个并行请求的竞争条件 (source)。

您可以将其他几个选项传递给 session 中间件,有关它们的更多信息,请参阅 API 文档

提示

请注意,secure: true 是推荐选项。但是,它需要启用 https 的网站,即 HTTPS 是安全 cookie 所必需的。如果设置了 secure,并且您通过 HTTP 访问您的网站,则不会设置 cookie。如果您的 node.js 位于代理后面并使用secure: true,则需要在 express 中设置trust proxy

设置完成后,您现在可以在路由处理程序中设置和读取会话值,如下所示:

ts
@Get()
findAll(@Req() request: Request) {
  request.session.visits = request.session.visits ? request.session.visits + 1 : 1;
}
提示

@Req() 装饰器从 @nestjs/common 导入,而 Requestexpress 包导入。

或者,您可以使用 @Session() 装饰器从请求中提取会话对象,如下所示:

ts
@Get()
findAll(@Session() session: Record<string, any>) {
  session.visits = session.visits ? session.visits + 1 : 1;
}
提示

@Session() 装饰器从 @nestjs/common 包导入。

与 Fastify 一起使用

首先安装所需的包:

shell
$ npm i @fastify/secure-session

安装完成后,注册 fastify-secure-session 插件:

ts
import secureSession from '@fastify/secure-session'

// somewhere in your initialization file
const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter(),
)
await app.register(secureSession, {
  secret: 'averylogphrasebiggerthanthirtytwochars',
  salt: 'mq9hDxBVDbspDR6n',
})
提示

您还可以预生成密钥(请参阅说明)或使用密钥轮换

官方存储库 中了解有关可用选项的更多信息。

有了这个,您现在可以在路由处理程序中设置和读取会话值,如下所示:

ts
@Get()
findAll(@Req() request: FastifyRequest) {
const visits = request.session.get('visits');
request.session.set('visits', visits ? visits + 1 : 1);
}

或者,您可以使用 @Session() 装饰器从请求中提取会话对象,如下所示:

ts
@Get()
findAll(@Session() session: secureSession.Session) {
  const visits = session.get('visits');
  session.set('visits', visits ? visits + 1 : 1);
}
提示

@Session() 装饰器从 @nestjs/common 导入,而 secureSession.Session@fastify/secure-session 包导入(导入语句:import * as secureSession from '@fastify/secure-session')。