多Scope(ACL)中间件绑定路由仅校验首个中间件的问题及/admin路由多角色权限适配方案需求
解决多角色权限中间件的路由访问问题
首先咱们来拆解下你遇到的核心问题:你的adminScope中间件是严格校验用户scope必须等于'admin',而超级管理员的scope是'superAdmin',所以当超级管理员访问/admin路由时,会被第一个中间件直接拦截返回403,根本到不了superAdminScope的校验环节。
下面给你两个实用的解决方案,按需选择:
方案一:打造通用多角色校验中间件(推荐)
写一个可复用的中间件,支持传入允许的角色列表,这样不管是admin+superAdmin还是其他角色组合,都能灵活适配:
// 通用权限校验中间件,接收允许的角色数组 const allowScopes = (allowedScopes) => { return (req, res, next) => { // 检查当前用户的scope是否在允许列表里 if (!allowedScopes.includes(req.user.scope)) { return res.status(403).send({ status: 'fail', message: `权限不足,需要以下任一角色:${allowedScopes.join(', ')}` }); } next(); }; };
然后在路由里这样使用:
app.use('/admin', [passport.authenticate('jwt', { session: false }), allowScopes(['admin', 'superAdmin'])], [adminPage] );
这个方案的优势是扩展性极强,以后新增角色或者调整权限组合,只需要修改传入的数组即可,不用重复写新的中间件。
方案二:直接修改现有admin中间件
如果你的权限组合比较固定,不想新增通用中间件,也可以直接修改adminScope,让它同时放行admin和superAdmin:
const adminScope = (req, res, next) => { // 只要是admin或superAdmin都能通过校验 if (!['admin', 'superAdmin'].includes(req.user.scope)) { return res.status(403).send({ status: 'fail', message: '你需要拥有管理员或超级管理员权限' }) } next(); };
然后路由只需要保留这个修改后的中间件:
app.use('/admin', [passport.authenticate('jwt', { session: false }), adminScope], [adminPage] );
为啥你之前的尝试没生效?
你之前把两个中间件按顺序叠加,或者嵌套数组的写法,本质上都是让中间件按顺序执行:先跑adminScope,超级管理员的scope不等于admin,直接被拦截返回了,所以superAdminScope根本没机会执行。另外,Express的中间件数组要求是一维的,嵌套数组的写法会被Express忽略,不会正确解析里面的中间件。
内容的提问来源于stack exchange,提问作者Omer Iqbal
相关产品推荐
相关产品推荐

