【权限】大家好,请教一个接口权限控制的问题
下面这端代码是我为我的小项目设计的权限控制的中间件,首先验证token是否合法,然后从token中提取出角色的信息,读取redis中该角色的权限,判断该角色是否拥有接口所需要的权限。
const jwt = require('jsonwebtoken')
const secret = require('../config/jwt').secret
const redisClient = require('../config/redis')
const { promisify } = require('util')
const getAsync = promisify(redisClient.get).bind(redisClient)
const acl = require('./../config/acl').acl
/**
* 登录权限控制
* @param {String} model 权限的模块
* @param {String} auth 权限名称
*/
module.exports = function (model, auth) {
return async function (ctx, next) {
const token = ctx.headers['x-access-token']
if (token) {
jwt.verify(token, secret, function (err, decoded) {
if (err) {
ctx.throw(403, 'token已过期')
} else {
// 使用redis进行登录的验证, 避免没有登录的时候, 使用之前的token进行访问
// 从token中获取id信息以及角色信息
const { id, role } = decoded
getAsync(id).then(res => {
if (!res) return ctx.throw(403, 'token失效')
ctx.decoded = decoded
if (!model || !auth) {
next()
} else {
// 接口权限验证
acl.areAnyRolesAllowed(role, model, auth, function (err, result) {
if (result) {
next()
} else {
return ctx.throw(403, '没有操作权限')
}
})
}
}).catch(err => {
return ctx.throw(403, 'token失效')
})
}
})
} else {
ctx.throw(403, '缺少token信息')
}
}
}
下面是我auth的schema的设计
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const AuthSchema = new Schema({
// 权限的代码
code: {
type: String,
unique: true,
required: true
},
// 权限的名称
name: {
type: String,
required: true
}
})
module.exports = AuthSchema
一个疑问,在做权限判断的时候,我应该使用auth的code还是auth的ObjectId做判断???????
2 回复
我觉得问题应该是指应该用哪个字段与角色关联,以及权限与资源如何绑定(推测是用code)。
- 角色使用code与权限项关联
相当于是在角色上冗余code字段,优点就是减少查询次数,缺点是权限项的维护复杂一些
- 角色使用ObjectId与权限项关联
查询的时候多查一下权限表,再判读角色是否有指定code的权限
各有优点,个人认为后者更合理。
建议token里不要放角色,token只是个用户id,然后把用户id与角色的映射放在权限中间件中。这样解耦合,方便修改角色。你的需求都可以用Casbin来做:https://github.com/casbin/node-casbin