朝阳博客

  • Article
  • Project
  • HTML+CSS
  • Bootstrap
  • JavaScript
  • jQuery
  • PHP
  • Java
  • Linux
  • MySQL
朝阳博客
一款专注于博客的响应式网站
  1. 首页
  2. 未分类
  3. 正文

Node.js 登录确权中间件

2026年3月17日 1点热度 0人点赞 0条评论
在 Web 系统中,**登录 ≠ 安全**。
真正决定系统安全性的,是 **登录后的“确权”能力**。

很多项目在登录之后,都会遇到这些问题:
  • Token 永久有效,无法主动失效
  • 用户修改密码后,旧登录仍然可用
  • 多端登录无法控制
  • Token 校验逻辑散落在各个接口
  • 高并发下,登录态校验性能差
这些问题的本质是:
> **缺少一个统一、可控、具备时效性的登录确权中间件**

一、什么是登录确权中间件?

登录 vs 确权

**确权发生在每一次 API 请求中。**

登录确权中间件的职责

  • 校验用户身份是否合法
  • 校验登录态是否过期
  • 控制登录时效
  • 支持主动失效
  • 给下游业务注入用户信息

二、为什么用 Redis 控制时效性?

仅用 JWT 的问题

JWT 常见方案:
登录成功 → 返回 JWT → 客户端每次请求携带

缺点非常明显:
❌ 无法主动失效
❌ Token 泄漏风险大
❌ 修改密码后旧 Token 仍可用
❌ 多端登录难控制

Redis 的优势

能力 Redis
TTL 自动过期 ✅
高并发 ✅
主动失效 ✅
多端控制 ✅
黑名单 ✅

一句话总结:
JWT 负责“身份声明”,Redis 负责“状态控制”

三、整体设计思路

登录流程

用户登录↓服务端校验账号密码↓生成 token↓token 存入 Redis(带 TTL)↓返回 token 给客户端

请求确权流程

请求进入↓登录确权中间件↓解析 token↓从 Redis 校验 token 是否存在 & 是否过期↓通过 → 放行失败 → 拦截

四、Redis 数据结构设计

方案一:token 作为 key(推荐)

login:token:{token} => userInfoTTL: 2h
示例:
login:token:abc123 => { userId: 1001, role: "admin" }
优点:
校验简单
删除即失效
天然支持 TTL

方案二:userId 作为 key(多端控制)

login:user:{userId}:{device} => token
适合:
单点登录
多端互斥

五、登录接口实现(示例)

const token = uuid();await redis.set(    login:token:</span><span class="code-snippet__string"><span class="code-snippet__subst">${token}</span></span><span class="code-snippet__string">,    JSON.stringify({ userId, role }),    'EX',    7200 // 2 小时);ctx.body = { token };

六、登录确权中间件核心实现(Koa)

中间件职责拆解

读取请求头 token
校验 token 是否存在
校验 Redis 中是否有效
注入用户信息到 ctx.state
失败则拦截请求

登录确权中间件代码示例

async function authMiddleware(ctx, next) {    const token = ctx.headers.authorization;    if (!token) {        ctx.status = 401;        ctx.body = { message: '未登录' };        return;    }    const key = login:token:</span><span class="code-snippet__string"><span class="code-snippet__subst">${token}</span></span><span class="code-snippet__string">;    const userStr = await redis.get(key);    if (!userStr) {        ctx.status = 401;        ctx.body = { message: '登录已过期' };        return;    }    const user = JSON.parse(userStr);    // 注入用户信息    ctx.state.user = user;    // 延长登录时效(滑动过期)    await redis.expire(key, 7200);    await next();}

七、滑动过期(非常重要)

什么是滑动过期?

用户持续操作 → 登录不失效
长时间不操作 → 自动过期
实现方式:
redis.expire(key, TTL);
放在每次成功校验后即可。

八、主动失效设计(退出登录)

退出登录

await redis.del(login:token:</span><span class="code-snippet__string"><span class="code-snippet__subst">${token}</span></span><span class="code-snippet__string">);
立即生效,无需等待过期。

修改密码 / 风控封禁

删除 Redis 中的 token
强制用户重新登录

九、多端登录控制(进阶)

单点登录设计

login:user:{userId} => token
流程:
新登录 → 查询旧 token
删除旧 token
写入新 token

示例逻辑

const oldToken = await redis.get(login:user:</span><span class="code-snippet__string"><span class="code-snippet__subst">${userId}</span></span><span class="code-snippet__string">);if (oldToken) {  await redis.del(login:token:</span><span class="code-snippet__string"><span class="code-snippet__subst">${oldToken}</span></span><span class="code-snippet__string">);}await redis.set(login:user:</span><span class="code-snippet__string"><span class="code-snippet__subst">${userId}</span></span><span class="code-snippet__string">, token);await redis.set(login:token:</span><span class="code-snippet__string"><span class="code-snippet__subst">${token}</span></span><span class="code-snippet__string">, userInfo, 'EX', 7200);

十、白名单 & 路由跳过

不需要确权的接口

/login
/register
/health

中间件中处理

const whiteList = ['/login', '/register'];  if (whiteList.includes(ctx.path)) {  return next();}

十一、安全与工程实践

1️⃣ token 设计

不要用 userId
使用 UUID / 随机字符串
长度 ≥ 32

2️⃣ token 存放位置

Header(推荐)
Authorization: Bearer xxx

3️⃣ Redis Key 规范化

login:token:login:user:

4️⃣ 不在 Redis 中存敏感信息

❌ 密码
❌ 明文手机号

十二、中间件加载顺序

app.use(errorHandler);app.use(authMiddleware);app.use(router.routes());
原则:
确权在业务之前,错误兜底在最前

十三、方案总结

一个成熟的登录确权中间件,应具备:
✅ Redis 控制登录时效
✅ 支持主动失效
✅ 支持滑动过期
✅ 中间件统一拦截
✅ 低侵入、高性能

一句话总结:
JWT 只是钥匙,Redis 才是门禁系统

标签: 暂无
最后更新:2026年3月17日

aiyao

你要加油,你喜欢的人还没结婚。

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2021 zhaoyangweb.com. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

冀ICP备2021020018号-1