express框架中登录使用redis保存token

发布于:2025-07-24 ⋅ 阅读:(24) ⋅ 点赞:(0)

(一)
1.电脑安装redis
下载地址
点击下载
提取码 wwhh

2.安装好后,进入到安装目录下启动redis
执行启动:

redis-server.exe redis.windows.conf

在这里插入图片描述
(二)Express 项目配置 Redis​

  1. expree项目安装redis依赖
npm install express redis dotenv

2.创建 .env 文件,复制下面的2行到.env文件中

REDIS_HOST=localhost
REDIS_PORT=6379

2.1创建 Redis 客户端,建议在应用入口app.js初始化
app.js文件

// app.js
// ... 其他 require 语句 ...
const redis = require('redis');
const config = require("./config");
var app = express();
var http = require("http");
var server = http.createServer(app);

// ========== Redis 客户端初始化(从这里开始添加) ==========
// 创建 Redis 客户端实例
const redisClient = redis.createClient({
  url: process.env.REDIS_URL || 'redis://localhost:6379' // 支持环境变量配置
});

// 处理连接错误
redisClient.on('error', (err) => {
  console.error('Redis连接错误:', err);
});

// 异步连接Redis
(async () => {
  try {
    await redisClient.connect();
    console.log('Redis连接成功');
  } catch (err) {
    console.error('Redis连接失败:', err);
    process.exit(1); // 如果Redis连接失败,退出应用
  }
})();

// 将redisClient挂载到app实例上,方便后续路由使用
app.locals.redisClient = redisClient;

// ========== Redis 初始化结束 ==========

// 错误处理中间件中添加 Redis 关闭逻辑
process.on('SIGINT', () => {
  redisClient.quit().then(() => {
    console.log('Redis连接已关闭');
    process.exit(0);
  });
});


server.listen("5000", () => {
  console.log("启动成功");
});

3.实现express登录接口保存token到redis

// 登录接口
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 导入jwt 包来生成token
const jwt = require("jsonwebtoken");
// 导入密钥
const config = require("../config");
exports.login = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // console.log('前端数据', userinfo)
  // 定义sql语句,根据用户名查询用户的信息
  const sql = `select * from ev_users where username=?`;
  // 执行sql语句,根据用户名查询用户的信息
  db.query(sql, userinfo.username, async (err, results) => {
    // 执行sql语句失败
    if (err) return res.cc(err);
    // 执行sql语句成功,但是获取到的数据条件不等于1
    if (results.length !== 1) return res.cc("登录失败!");
    const compareResult = bcrypt.compareSync(
      userinfo.password,
      results[0].password
    );


    if (!compareResult) {
      return res.cc("登录失败!");
    }
    // 生成jwt的token字符串
    // 清空用户信息的密码和头像
    const user = {
      ...results[0],
      password: "",
      user_pic: ""
    };
    console.log("YONGHU", user);
    // 对用户的信息进行加密,生成token字符串
    const tokenStr = jwt.sign(user, config.jwtSecretKey, {
      expiresIn: "10h", // token 有效期为10小时
    });

    try {
      // 获取Redis客户端实例
      const redisClient = req.app.locals.redisClient;

      // 将Token存储到Redis
      await redisClient.setEx(
        `token:${user.id}`, // 键名格式: token:用户ID
        36000, // 过期时间(秒): 10小时 = 3600秒/小时 × 10
        tokenStr // 值: JWT令牌字符串
      );

      const storedToken = await redisClient.get(`token:${user.id}`);
      console.log('[Redis验证] 存储的Token:', storedToken);
      console.log('[Redis验证] 剩余TTL:', await redisClient.ttl(`token:${user.id}`));


      console.log(`Token已存入Redis (用户ID: ${user.id})`);

      // 响应客户端保持不变
      res.send({
        status: 0,
        message: "登录成功!",
        token: "Bearer " + tokenStr,
      });

    } catch (redisError) {
      console.error('Redis存储失败:', redisError);
      // Redis错误时仍返回登录成功,但记录错误信息
      res.send({
        status: 0,
        message: "登录成功,但Token缓存失败",
        token: "Bearer " + tokenStr,
      });
    }

  });
};


  1. 验证 Redis 存储​

前端或者用postman发送登录接口,登录成功后验证redis里面是否存在token

1.前端登录成功
在这里插入图片描述

2.验证token 是否在redis

在 Redis 目录下启动 CLI
redis-cli.exe
查询数据
127.0.0.1:6379> KEYS *

此时ID为46的token 保存到了redis中
在这里插入图片描述
退出登录后从redis里面删除token

退出登录接口

exports.logout = async (req, res) => {
  try {
    // 从请求头获取token (格式: Bearer <token>)
    const tokenHeader = req.headers.authorization;
    
    if (!tokenHeader || !tokenHeader.startsWith('Bearer ')) {
      return res.cc("授权信息无效", 1);
    }
    
    // 提取实际token值 (去除"Bearer "前缀)
    const token = tokenHeader.split(' ')[1];
    
    // 验证并解码token
    let decoded;
    try {
      decoded = jwt.verify(token, config.jwtSecretKey);
    } catch (err) {
      // Token无效(过期或签名错误)
      return res.cc("授权信息已过期或无效", 1);
    }
    
    // 获取Redis客户端
    const redisClient = req.app.locals.redisClient;
    
    // 从Redis删除该用户的token
    const deleteResult = await redisClient.del(`token:${decoded.id}`);
    
    if (deleteResult === 1) {
      console.log(`用户 ${decoded.id} 退出登录成功,Token已删除`);
      res.cc("退出登录成功", 0);
    } else {
      console.log(`用户 ${decoded.id} 退出登录但Token未找到`);
      res.cc("退出登录成功", 0); // 即使未找到也返回成功,可能已过期
    }
    
  } catch (err) {
    console.error("退出登录处理错误:", err);
    res.cc("服务器内部错误", 1);
  }
};

网站公告

今日签到

点亮在社区的每一天
去签到