高安全架构 学习笔记(第 10 部分)
5.3 RBAC 权限控制
javascript
// RBAC (基于角色的访问控制)
class RBAC {
constructor() {
// 定义角色
this.roles = {
admin: {
permissions: ['*'], // 所有权限
description: '超级管理员'
},
editor: {
permissions: [
'content:read',
'content:write',
'content:delete',
'user:read'
],
description: '编辑'
},
viewer: {
permissions: [
'content:read',
'user:read'
],
description: '查看者'
}
}
// 用户角色映射
this.userRoles = new Map()
}
// 分配角色
assignRole(userId, role) {
if (!this.roles[role]) {
throw new Error(`角色 ${role} 不存在`)
}
if (!this.userRoles.has(userId)) {
this.userRoles.set(userId, new Set())
}
this.userRoles.get(userId).add(role)
}
// 撤销角色
revokeRole(userId, role) {
if (this.userRoles.has(userId)) {
this.userRoles.get(userId).delete(role)
}
}
// 检查权限
hasPermission(userId, permission) {
const roles = this.userRoles.get(userId)
if (!roles) return false
for (const role of roles) {
const permissions = this.roles[role].permissions
// 通配符权限
if (permissions.includes('*')) return true
// 精确匹配
if (permissions.includes(permission)) return true
// 通配符匹配
if (this.matchWildcard(permission, permissions)) return true
}
return false
}
// 通配符匹配
matchWildcard(permission, permissions) {
for (const perm of permissions) {
if (perm.includes('*')) {
const pattern = perm.replace('*', '.*')
const regex = new RegExp(`^${pattern}$`)
if (regex.test(permission)) return true
}
}
return false
}
// 权限检查中间件
requirePermission(permission) {
return (req, res, next) => {
const userId = req.user.userId
if (!this.hasPermission(userId, permission)) {
return res.status(403).json({
error: 'Forbidden',
message: '权限不足'
})
}
next()
}
}
// 获取用户所有权限
getUserPermissions(userId) {
const roles = this.userRoles.get(userId)
if (!roles) return []
const allPermissions = new Set()
for (const role of roles) {
const permissions = this.roles[role].permissions
permissions.forEach(p => allPermissions.add(p))
}
return Array.from(allPermissions)
}
}
// 使用示例
const rbac = new RBAC()
// 分配角色
rbac.assignRole('user123', 'editor')
// 检查权限
console.log(rbac.hasPermission('user123', 'content:write')) // true
console.log(rbac.hasPermission('user123', 'user:delete')) // false
// 在路由中使用
app.delete('/content/:id',
auth.authenticate(),
rbac.requirePermission('content:delete'),
(req, res) => {
res.json({ message: '内容删除成功' })
}
)