1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
| // 权限定义
interface Permission {
resource: string; // 资源类型
action: string; // 操作类型
condition?: (context: any) => boolean;
}
// 角色定义
interface Role {
name: string;
permissions: Permission[];
}
// RBAC实现
class RBACService {
private roles = new Map<string, Role>();
constructor() {
this.initializeRoles();
}
private initializeRoles(): void {
// 管理员角色
this.roles.set('admin', {
name: 'admin',
permissions: [
{ resource: '*', action: '*' } // 全部权限
]
});
// 编辑角色
this.roles.set('editor', {
name: 'editor',
permissions: [
{ resource: 'posts', action: 'create' },
{ resource: 'posts', action: 'update' },
{ resource: 'posts', action: 'delete', condition: ctx => ctx.resource.ownerId === ctx.user.userId },
{ resource: 'posts', action: 'read' },
{ resource: 'comments', action: 'moderate' }
]
});
// 普通用户角色
this.roles.set('user', {
name: 'user',
permissions: [
{ resource: 'posts', action: 'read' },
{ resource: 'comments', action: 'create' },
{ resource: 'comments', action: 'update', condition: ctx => ctx.resource.ownerId === ctx.user.userId },
{ resource: 'comments', action: 'delete', condition: ctx => ctx.resource.ownerId === ctx.user.userId }
]
});
}
// 检查权限
async checkPermission(
user: User,
resource: string,
action: string,
context?: any
): Promise<boolean> {
// 获取用户角色
const userRoles = await this.getUserRoles(user.userId);
for (const roleName of userRoles) {
const role = this.roles.get(roleName);
if (!role) continue;
for (const perm of role.permissions) {
// 通配符匹配
if (perm.resource === '*' && perm.action === '*') {
return true;
}
// 资源和操作匹配
if (
this.matchPattern(perm.resource, resource) &&
this.matchPattern(perm.action, action)
) {
// 检查条件
if (perm.condition) {
return perm.condition(context);
}
return true;
}
}
}
return false;
}
// 权限中间件
requirePermission(resource: string, action: string) {
return async (request: Request, response: Response, next: NextFunction) => {
const hasPermission = await this.checkPermission(
request.user,
resource,
action,
{ resource: request.resource, user: request.user }
);
if (!hasPermission) {
throw new ForbiddenError('Insufficient permissions');
}
next();
};
}
private matchPattern(pattern: string, value: string): boolean {
// 简单的通配符匹配
const regex = new RegExp(
'^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$'
);
return regex.test(value);
}
}
|