使用Session

Express本身没有对Session进行支持,不过我们可以使用express-session库,它以中间件的形式封装了Session实现,底层可以使用内存、Redis、MongoDB等后端保存数据。

安装express-session

执行以下命令安装express-session库。

npm i express-session

基本使用

下面是一个简单的例子,我们使用基于内存的Session后端。

import express from "express";
import expressSession from "express-session";

const app = express();

// 初始化Session中间件
const session = expressSession({
  secret: "G1Wdumt0xvLFtnbBTvj%GKeDpw5xjkCv!HViqSWJ$cKPAun@Gq",
  resave: true,
  saveUninitialized: false,
});

// 注册Session中间件
app.use(session);

// 路由处理
app.get("/", (req, res) => {
  // 读取Session
  const user = req.session.user;
  console.log(user);
  // 写入Session
  req.session.user = { name: "Tom", age: 18 };
  res.sendStatus(200);
});

app.listen(8080, () => {
  console.log("Express server listen on 8080");
});

代码中,我们首先初始化了Session中间件,常用配置项如下:

  • secret:加密密钥,express-session会使用该密钥对Session ID进行签名,防止被篡改
  • resave:是否在Session未改变时也强制重新保存,一般设置为true
  • saveUninitialized:是否保存未初始化的Session,一般设置为false

session对象实际上是一个Express中间件,我们需要使用app.use()将其添加到框架中,注意它需要设置在路由处理之前。在具体的处理函数中,我们直接对req.session属性进行读写即可实现对Session数据的读写。

注意:默认情况下,Cookie中保存Session ID的键名为connect.sid

常用配置项

除了上面介绍的基本配置外,express-session还支持更多配置项。

const session = expressSession({
  secret: "your-secret-key",
  resave: true,
  saveUninitialized: false,
  name: "sessionId",
  cookie: {
    maxAge: 1000 * 60 * 60 * 24, // 过期时间,单位毫秒
    httpOnly: true,
    secure: false,
  },
});
  • name:Cookie中Session ID的键名,默认为connect.sid
  • cookie.maxAge:Session过期时间,单位为毫秒
  • cookie.httpOnly:是否禁止JavaScript访问Cookie,建议设置为true
  • cookie.secure:是否仅在HTTPS下传输Cookie,生产环境建议设置为true

销毁Session

我们可以调用req.session.destroy()方法销毁当前Session,这在用户退出登录等场景中非常有用。

app.get("/logout", (req, res) => {
  req.session.destroy((err) => {
    if (err) {
      console.error("Session destroy error:", err);
      res.sendStatus(500);
    } else {
      res.sendStatus(200);
    }
  });
});

使用Redis作为Session存储

在生产环境中,基于内存的Session存储存在一些问题:服务重启后Session数据会丢失,多进程或分布式部署时Session无法共享。我们可以使用Redis作为Session存储后端来解决这些问题。

首先安装connect-redis库。

npm i connect-redis redis

然后配置Redis作为Session存储。

import express from "express";
import expressSession from "express-session";
import RedisStore from "connect-redis";
import { createClient } from "redis";

const app = express();

// 创建Redis客户端
const redisClient = createClient({
  url: "redis://localhost:6379",
});
redisClient.connect().catch(console.error);

// 初始化Session中间件
const session = expressSession({
  store: new RedisStore({ client: redisClient }),
  secret: "G1Wdumt0xvLFtnbBTvj%GKeDpw5xjkCv!HViqSWJ$cKPAun@Gq",
  resave: false,
  saveUninitialized: false,
});

app.use(session);

app.get("/", (req, res) => {
  const user = req.session.user;
  console.log(user);
  req.session.user = { name: "Tom", age: 18 };
  res.sendStatus(200);
});

app.listen(8080, () => {
  console.log("Express server listen on 8080");
});

使用Redis作为存储后端时,resave配置项建议设置为false,因为Redis存储本身会自动处理过期时间的刷新。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。