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

Express中间件两种认证写法对比:哪种更优及原因?

推荐哪种Express认证中间件写法?

先把两种实现方式明确列出来:

方式一:直接通过router.use挂载全局中间件

router.use((req, res, next) => { // 作为单个路由导出到文件中
  if (req.isAuthenticated()) {
    next();
    return;
  }
  res.sendStatus(401);
});

方式二:封装为独立命名函数

const authenticate = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
    return;
  }
  res.sendStatus(401);
};
// 使用示例
router.post('/', authenticate, (req, res, next) => {});

毫无疑问,第二种封装成命名函数的写法更值得推荐,核心原因如下:

  • 复用性更灵活:第一种写法会强制给当前router下的所有路由加上认证逻辑,要是这个路由文件里存在不需要认证的公开接口(比如首页查询、验证码接口),这种写法就直接失效了。而命名函数的方式可以按需给单个/部分路由添加认证,不管是同一个router还是不同的路由模块,都能直接调用,适配更多场景。

  • 可读性与可维护性更强:authenticate这个名字直接点明了函数作用,其他开发者看代码时一眼就能理解这个中间件的用途。后续如果要修改认证逻辑(比如新增权限校验、调整错误返回格式),只需要修改这一个函数即可,不用在各个router.use的位置到处找代码。

  • 测试成本更低:独立的命名函数可以脱离Express环境做单元测试,你只需要模拟req、res、next对象,就能验证认证逻辑的正确性,不需要启动整个服务,测试效率高很多。

  • 扩展能力拉满:如果后续需要区分不同权限的认证(比如普通用户、管理员),可以轻松改造成高阶函数:

    const authenticate = (requiredRole) => {
      return (req, res, next) => {
        if (req.isAuthenticated() && req.user.role === requiredRole) {
          next();
          return;
        }
        res.sendStatus(requiredRole ? 403 : 401);
      };
    };
    // 使用示例:管理员专属接口
    router.post('/admin/dashboard', authenticate('admin'), (req, res) => {});
    

    这种扩展能力是第一种写法完全无法实现的。

当然第一种写法也有适用场景:如果某个路由模块下的所有接口都必须认证,直接用router.use挂载确实省事,但这种场景相对有限,绝大多数业务场景下,第二种写法的通用性和灵活性都更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:24:23