You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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,就会触发未登录错误。

排查与修复步骤

  1. 检查前端请求逻辑:给登出按钮添加防抖逻辑,点击后立即禁用按钮,直到收到后端响应再恢复,避免重复发送请求。
  2. 验证路由配置:确保登出路由的中间件顺序正确,isAuthenticated必须放在控制器之前,示例配置如下:
// 路由配置示例
import { logoutUser } from "../controllers/auth.controller";
import { isAuthenticated } from "../middleware/auth";

router.post("/logout", isAuthenticated, logoutUser);
  1. 调试中间件:在isAuthenticated中添加日志,打印req.cookies.access_token的值,确认请求时是否携带有效token:
console.log("当前请求的access_token:", req.cookies.access_token);
  1. 修复代码拼写错误:登出控制器响应中的suceess是拼写错误,改为success,避免前端解析异常。

优化建议

  • 登出时可将access_token加入Redis黑名单(设置与token有效期一致的过期时间),避免已登出的token被恶意使用。
  • 在认证中间件中新增黑名单校验逻辑,拒绝已登出的token请求。

内容的提问来源于stack exchange,提问作者Aman Maddheshiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:40:01