Node.js Express 中间件鉴权漏掉部分路由导致 403 Forbidden 怎么办?

Node.js Express 中间件鉴权配置不当导致部分路由 403 Forbidden 怎么办?

直接检查中间件挂载顺序和路由路径匹配,通常是因为鉴权中间件被错误地应用到了本应公开的路由,或者请求头处理不当导致验证失败。

先说结论:问题多出在中间件执行顺序、路由挂载路径不一致或请求头大小写处理上。

  • 先确认中间件注册顺序
  • 先处理路由挂载路径匹配
  • 再验证请求头大小写规范

核心原因分析

Express 按注册顺序执行中间件。如果鉴权中间件注册在所有路由之前且没有排除逻辑,所有请求都会被拦截。此外,Express 会自动将 HTTP 请求头名称转换为小写,如果代码中尝试获取 Authorization 而非 authorization,会导致无法读取 Token 从而返回 403。

解决方案一:调整中间件注册顺序

确保公开路由(如登录、注册)在鉴权中间件之前注册。

// 检查 app.js 或入口文件中的中间件顺序
app.use('/api/login', loginRouter);   // 公开路由在前
app.use('/api', authMiddleware);      // 鉴权中间件在后
app.use('/api', protectedRouter);     // 受保护路由

解决方案二:完善中间件内部路径排除逻辑(推荐)

仅调整顺序可能无法解决复杂路由结构下的鉴权冲突,建议在中间件内部实现路径白名单。

const authMiddleware = (req, res, next) => {
  // 白名单路径,无需鉴权
  const publicPaths = ['/api/login', '/api/register', '/api/public'];
  if (publicPaths.some(path => req.path.startsWith(path))) {
    return next();
  }
  // 获取请求头,Express 会自动转小写
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(403).json({ error: 'Unauthorized' });
  }
  const token = authHeader.split(' ')[1];
  // 此处添加 token 验证逻辑
  // verifyToken(token)...
  next();
};

请求头大小写处理

在中间件中使用 req.headers.authorization 而不是 req.headers['Authorization'],因为 Express 会将头名称转为小写。

验证方法

使用 curl 命令测试受保护接口:

curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/api/protected

观察是否返回 200 而非 403。同时检查服务器日志,确认中间件是否按预期跳过或通过了验证。

常见坑与排查

  • 请求头大小写:客户端发送 Authorization,服务端必须用 authorization 读取。
  • 路由前缀 mismatch:app.use('/list', router) 意味着内部路由 / 对应外部 /list,而非根路径。
  • 中间件顺序:app.use(auth) 放在 app.use(routes) 之后会导致鉴权不生效,放在之前且无排除逻辑会导致公开接口 403。
  • 复杂路由结构:如果路由分散在不同文件,仅靠顺序难以管理,务必使用中间件内部路径判断。

参考文档

  • Express 官方文档:Using Middleware
  • MDN Web Docs: HTTP Headers

原文链接:https://www.zjcp.cc/ask/11373.html

posted @ 2026-05-17 20:49  茶猫云呀  阅读(2)  评论(0)    收藏  举报