基于LMS系统的后端认证登出错误:Access Token匹配失败
问题排查:登出路由触发认证中间件的未登录错误
我正在开发一款基于LMS的软件,负责认证模块,技术栈为TypeScript、Redis和MongoDB。目前已实现Register、Activate-user、login、logout四个路由,登录时能成功生成access token和refresh token,但执行登出操作时,触发了认证逻辑中「请登录以访问所有资源」的错误(该错误在access token不存在或无效时抛出)。我希望通过认证中间件完成登出,但却触发了这个错误,请求协助排查原因。
访问登出路由时的错误截图

认证中间件 auth.ts 代码
import { NextFunction, Request, Response } from "express"; import { catchAsyncError } from "./catchAsyncError"; import ErrorHandler from "../utils/ErrorHandler"; import jwt, { JwtPayload } from "jsonwebtoken"; import { redis } from "../utils/redis"; export const isAuthenticated = catchAsyncError(async(req: Request, res: Response, next: NextFunction) =>{ const access_token = req.cookies.access_token as string; if(!access_token){ return next(new ErrorHandler("Please login to access all the resources.", 400)); } const decoded = jwt.verify(access_token, process.env.ACCESS_TOKEN as string) as JwtPayload; if(!decoded){ return next(new ErrorHandler("access token is not valid", 400)); } const user = await redis.get(decoded.id); if(!user){ return next(new ErrorHandler("user not found", 400)); } req.user = JSON.parse(user); next(); });
登出控制器代码

// LOGOUT USER export const logoutUser= catchAsyncError( async (req:Request, res:Response, next:NextFunction) =>{ try { res.cookie("access_token", "", {maxAge:1}); res.cookie("refresh_token", "", {maxAge:1}); // delete data from redis database const userId = req.user?._id || ""; // console.log(req.user); redis.del(userId); res.status(200).json({ suceess:true, message:"Logged out successfully", }); } catch (error:any) { return next(new ErrorHandler(error.message, 400)); } } );
原因分析与解决方案
核心问题
大概率是重复请求导致的冲突:第一次登出请求携带有效access_token通过认证中间件,执行逻辑时会清空access_token的cookie;如果前端短时间内重复发送登出请求(比如按钮未加防抖),第二次请求的cookie中已经没有有效token,就会触发未登录错误。
排查与修复步骤
- 检查前端请求逻辑:给登出按钮添加防抖逻辑,点击后立即禁用按钮,直到收到后端响应再恢复,避免重复发送请求。
- 验证路由配置:确保登出路由的中间件顺序正确,
isAuthenticated必须放在控制器之前,示例配置如下:
// 路由配置示例 import { logoutUser } from "../controllers/auth.controller"; import { isAuthenticated } from "../middleware/auth"; router.post("/logout", isAuthenticated, logoutUser);
- 调试中间件:在
isAuthenticated中添加日志,打印req.cookies.access_token的值,确认请求时是否携带有效token:
console.log("当前请求的access_token:", req.cookies.access_token);
- 修复代码拼写错误:登出控制器响应中的
suceess是拼写错误,改为success,避免前端解析异常。
优化建议
- 登出时可将access_token加入Redis黑名单(设置与token有效期一致的过期时间),避免已登出的token被恶意使用。
- 在认证中间件中新增黑名单校验逻辑,拒绝已登出的token请求。
内容的提问来源于stack exchange,提问作者Aman Maddheshiya
相关产品推荐
相关产品推荐

