如何创建用于验证订阅状态的全局中间件?
如何实现订阅验证中间件(用户付费状态校验)
核心逻辑
中间件的核心作用是在请求到达业务接口前,拦截并校验用户是否拥有有效且未过期的付费订阅,校验通过则放行请求,否则直接返回权限错误。
具体实现步骤
- 提取用户身份:从请求头(如
Authorization中的JWT令牌)、请求参数或会话中获取用户唯一标识(如userId) - 校验订阅状态:查询内部订阅服务或数据库,确认用户的订阅是否处于
active状态、是否在有效期内 - 拦截/放行判断:订阅有效则继续执行后续业务逻辑;无效则返回
403 Forbidden或自定义错误响应
代码示例(Express.js)
// 订阅验证中间件 const checkValidSubscription = async (req, res, next) => { // 1. 解析用户身份 const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ msg: '请提供有效认证令牌' }); } const token = authHeader.split(' ')[1]; let userId; try { const decoded = jwt.verify(token, process.env.JWT_SECRET); userId = decoded.userId; } catch (err) { return res.status(401).json({ msg: '认证令牌无效' }); } // 2. 查询用户有效订阅(模拟调用订阅服务) const activeSubscription = await subscriptionDb.query( 'SELECT * FROM subscriptions WHERE user_id = ? AND status = "active" AND expiry_date > NOW()', [userId] ); if (!activeSubscription[0]) { return res.status(403).json({ msg: '您没有有效订阅,请完成付费后再操作' }); } // 3. 订阅有效,挂载信息供后续接口使用 req.subscription = activeSubscription[0]; next(); }; // 给需要校验的路由挂载中间件 app.use('/premium/api/*', checkValidSubscription);
关键注意事项
- 缓存优化:若订阅状态不会频繁变更,可将校验结果缓存至Redis,减少数据库查询压力
- 错误区分:明确区分
401(未认证)和403(无权限),给用户清晰的错误指引 - 异步处理:确保中间件正确处理异步查询逻辑,避免请求阻塞或未捕获的Promise异常
- 原子性校验:查询订阅状态时,需保证数据的一致性(如使用数据库事务或行锁)
内容的提问来源于stack exchange,提问作者EdsonMeza97
相关产品推荐
相关产品推荐

