Node.js(Express)全局路由前拦截请求头及统一鉴权方案问询
当然可行!这正是Node.js Web框架(比如最常用的Express)里中间件的核心应用场景之一——把重复的授权校验逻辑抽出来,统一在路由处理前执行,完美解决你现在每个路由都要写冗余验证代码的问题。
下面我给你一步步拆解实现方案:
1. 先编写令牌验证中间件
中间件本质是一个能访问请求对象(req)、响应对象(res)和下一个中间件函数(next)的函数。我们把令牌校验的逻辑全部封装在这里:
// 假设你用jsonwebtoken处理JWT令牌,先安装依赖:npm install jsonwebtoken const jwt = require('jsonwebtoken'); const authMiddleware = (req, res, next) => { // 1. 从请求头获取Authorization字段 const authHeader = req.headers.authorization; // 2. 检查令牌格式是否合法(标准格式是 Bearer <token>) if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: '未提供有效的身份令牌' }); } // 3. 提取出纯令牌内容 const token = authHeader.split(' ')[1]; try { // 4. 验证令牌有效性(替换成你的JWT密钥和自定义验证逻辑) const decodedUser = jwt.verify(token, process.env.JWT_SECRET); // 5. 把验证通过的用户信息挂载到req上,方便后续路由直接使用 req.user = decodedUser; // 6. 校验通过,放行到下一个路由处理函数 next(); } catch (error) { // 令牌无效/过期,返回401未授权 return res.status(401).json({ message: '令牌无效或已过期' }); } };
2. 给路由批量/按需应用中间件
你有几种灵活的方式来给路由添加这个校验逻辑,根据你的路由结构选就行:
方式一:给指定前缀的路由统一加校验
如果你的需要授权的接口都有统一前缀(比如/api),可以直接给这个前缀的所有路由批量应用中间件,同时把不需要校验的/login放在前面:
const express = require('express'); const app = express(); // 先注册无需校验的登录接口(中间件按顺序执行,放在前面就不会被拦截) app.post('/login', (req, res) => { // 你的登录逻辑:验证账号密码,生成令牌返回给客户端 res.json({ token: '生成的JWT令牌' }); }); // 给所有/api开头的接口统一应用授权校验 app.use('/api', authMiddleware); // 接下来的/api接口都会先经过校验 app.get('/api/user/profile', (req, res) => { // 这里可以直接用req.user,中间件已经把用户信息挂载好了 res.json({ userInfo: req.user }); }); app.post('/api/orders', (req, res) => { // 业务逻辑:创建订单 res.json({ message: '订单创建成功' }); });
方式二:给单个路由单独加校验
如果你的路由比较零散,也可以给需要校验的路由单独添加中间件:
// 无需校验的路由 app.post('/login', (req, res) => { /* ... */ }); app.get('/public/announcement', (req, res) => { /* ... */ }); // 需要校验的路由,把中间件放在业务处理函数前面 app.get('/user/profile', authMiddleware, (req, res) => { /* ... */ }); app.post('/orders', authMiddleware, (req, res) => { /* ... */ });
方式三:给路由分组加校验(适合大型项目)
如果用Express Router做路由分组,可以给整个路由组应用中间件:
const apiRouter = express.Router(); // 给整个api路由组添加校验 apiRouter.use(authMiddleware); // 在路由组里定义具体接口 apiRouter.get('/user/profile', (req, res) => { /* ... */ }); apiRouter.post('/orders', (req, res) => { /* ... */ }); // 把路由组挂载到主应用 app.use('/api', apiRouter); // 无需校验的路由单独注册 app.post('/login', (req, res) => { /* ... */ });
3. 额外:排除特定无需校验的路径
如果不想调整路由顺序,也可以在中间件里直接排除不需要校验的路径:
const authMiddleware = (req, res, next) => { // 定义无需校验的路径列表 const excludedPaths = ['/login', '/register', '/public']; if (excludedPaths.includes(req.path)) { return next(); // 直接放行 } // 剩下的令牌校验逻辑和之前一样 // ... }; // 现在可以把中间件放在所有路由前面 app.use(authMiddleware); app.post('/login', (req, res) => { /* ... */ }); app.get('/api/user/profile', (req, res) => { /* ... */ });
这种统一校验的方式最大的好处就是代码复用、集中维护——后续如果要修改令牌校验规则(比如换加密算法、添加权限细分),只需要改这一个中间件就行,不用逐个路由去调整,非常高效。
内容的提问来源于stack exchange,提问作者Marco Jr
相关产品推荐
相关产品推荐

