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

如何将中间件中的值传递给后续控制器(Token认证场景)

如何将中间件中的值传递给后续控制器(Token认证场景)

兄弟我懂你这种挠头的感觉!之前我也遇到过类似的情况,在非Express的环境里没法直接用req.user或者res.locals,确实头疼。针对你这种Token认证后传递用户数据的需求,给你几个靠谱的方案,不用在每个控制器里重复调用函数:

  • 利用Node.js原生的Async Local Storage实现请求上下文
    这是个通用型的方案,不管你用什么Node.js框架都能用上。它能在整个异步调用链中保存上下文数据,完美解决跨中间件、跨控制器的传值问题。举个实际代码例子:

    // 初始化Async Local Storage
    const { AsyncLocalStorage } = require('async_hooks');
    const als = new AsyncLocalStorage();
    
    // 认证中间件:解析Token并存储用户数据
    const authMiddleware = async (req, res, next) => {
      // 这里替换成你的Token验证逻辑,解析出用户数据
      const userData = await verifyToken(req.headers.authorization?.split(' ')[1]);
      // 启动上下文并存储用户数据
      als.run(new Map(), () => {
        als.getStore().set('currentUser', userData);
        next(); // 放行到后续控制器
      });
    };
    
    // 任意控制器中获取用户数据
    const getUserProfileController = (req, res) => {
      const currentUser = als.getStore().get('currentUser');
      res.json({ userId: currentUser.id, username: currentUser.username });
    };
    

    这种方式不用修改请求/响应对象,而且在任何异步嵌套的函数里都能拿到用户数据,非常灵活。

  • 自定义扩展请求对象
    如果你的框架允许自定义请求对象(比如Fastify、Koa都有类似机制),可以参照Express的req.user思路,给请求对象添加自定义属性。比如:

    // 自定义请求类(以某框架为例)
    class CustomRequest extends FrameworkBaseRequest {
      constructor(rawReq) {
        super(rawReq);
        this.currentUser = null; // 预留用户属性
      }
    }
    
    // 在框架配置中替换默认请求类为自定义类
    frameworkInstance.config({
      requestClass: CustomRequest
    });
    
    // 认证中间件中赋值
    const authMiddleware = async (req, res, next) => {
      const userData = await verifyToken(req.headers.authorization?.split(' ')[1]);
      req.currentUser = userData; // 直接给自定义请求对象赋值
      next();
    };
    
    // 控制器中直接使用
    const orderListController = (req, res) => {
      console.log(`获取用户${req.currentUser.id}的订单列表`);
      // 业务逻辑...
    };
    

    这个方案最贴近你熟悉的Express用法,学习成本低,代码也直观。

  • 借助依赖注入(DI)实现解耦传递
    如果你的项目是大型架构,用了依赖注入框架(比如TypeDI、NestJS的DI系统),可以把用户数据注入到需要的控制器中,彻底解耦中间件和控制器:

    // 认证中间件:将用户数据绑定到请求作用域的DI容器
    const authMiddleware = async (req, res, next) => {
      const userData = await verifyToken(req.headers.authorization?.split(' ')[1]);
      // 以TypeDI为例,绑定请求作用域的用户实例
      container.register({ id: 'CurrentUser', useValue: userData }, { scope: Scope.Request });
      next();
    };
    
    // 控制器通过DI注入用户数据
    class UserController {
      constructor(@Inject('CurrentUser') private currentUser) {}
    
      async getProfile(req, res) {
        res.json({
          id: this.currentUser.id,
          email: this.currentUser.email
        });
      }
    }
    

    这种方式适合追求代码架构整洁、可测试性高的项目,控制器不用关心用户数据从哪来,只需要用就行。

你可以根据自己项目所用的框架、规模大小来选择合适的方案,都能完美解决你不想重复调用函数的痛点。

备注:内容来源于stack exchange,提问作者Waqas Akbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 06:58:05