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

Express+Passport应用:会话过期时如何实现登出跳转至登录页?

解决JWT会话过期时的登出与页面跳转问题

让我们一步步拆解你的问题,先明确JWT认证的核心特性,再对应给出后端和前端的处理方案:

一、后端路由的处理:统一捕获认证失败,无需逐个路由修改

你的代码里已经用了passport.authenticate('jwt', { session: false })作为路由中间件,这个中间件会自动验证JWT的有效性——当token过期、无效或者缺失时,Passport会抛出UnauthorizedError错误。

你不需要在每个业务路由(比如dailyInfoRoute)里单独处理过期逻辑,只需要在所有路由注册完成后添加一个全局错误处理中间件,统一捕获JWT认证失败的情况,返回标准的401状态码:

// 在routes.js的末尾,所有app.use路由注册之后添加
module.exports = (app, passport) => {
  // ...你的所有路由注册代码...

  // 全局错误处理中间件,捕获JWT认证失败
  app.use((err, req, res, next) => {
    if (err.name === 'UnauthorizedError') {
      // 返回401状态码和提示信息
      return res.status(401).json({ 
        success: false, 
        message: '会话已过期,请重新登录' 
      });
    }
    // 传递其他错误给下一个中间件
    next(err);
  });
};

这样所有需要JWT认证的路由,在token过期时都会触发这个错误处理,返回统一的响应,不需要在dailyInfoRoute这类业务路由里额外写逻辑。

二、前端处理:拦截401响应,执行登出并跳转登录页

JWT是无状态的,服务器不会存储会话信息,所以"登出"本质是客户端清除本地存储的JWT token。当后端返回401时,前端需要拦截这个响应,执行以下操作:

  1. 清除本地存储的JWT token(比如localStorage或sessionStorage)
  2. 跳转到登录页面

以Axios为例,你可以添加响应拦截器来实现:

// 前端API请求拦截器
axios.interceptors.response.use(
  response => response,
  error => {
    // 捕获401状态码
    if (error.response?.status === 401) {
      // 清除本地token
      localStorage.removeItem('jwtToken');
      // 跳转到登录页(根据你的前端路由调整路径)
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

如果用其他请求库(比如fetch),也可以封装统一的请求函数,在处理响应时判断状态码并执行跳转。

三、额外优化:整理路由结构,减少重复代码

看你的routes.js里,有大量重复的passport.authenticate('jwt', { session: false })调用,还重复注册了status路由。可以把需要认证的路由分组,简化代码:

module.exports = (app, passport) => {
  var config = require('../Config/Config');
  // 导入所有路由模块
  var autho = require('../routes/authoRoute.js');
  var user = require('../routes/userRoute.js');
  var status = require('../routes/statusRoute.js');
  // ...其他路由模块导入...

  // 不需要认证的路由(比如登录、注册)
  app.use(config.mainRoute.route, autho(passport));

  // 创建一个路由组,统一应用JWT认证中间件
  const protectedRoutes = require('express').Router();
  // 把所有需要认证的路由挂载到这个组里
  protectedRoutes.use(user(passport));
  protectedRoutes.use(status(passport));
  protectedRoutes.use(department(passport));
  protectedRoutes.use(testroom(passport));
  // ...其他需要认证的路由...

  // 为整个路由组应用JWT认证
  app.use(config.mainRoute.route, passport.authenticate('jwt', { session: false }), protectedRoutes);

  // 全局错误处理中间件
  app.use((err, req, res, next) => {
    if (err.name === 'UnauthorizedError') {
      return res.status(401).json({ 
        success: false, 
        message: '会话已过期,请重新登录' 
      });
    }
    next(err);
  });
};

这样不仅代码更简洁,也避免了重复注册路由的问题。

内容的提问来源于stack exchange,提问作者Miguel-Ángel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:03:14