权限划分
- 页面权限(按钮、菜单,权限更新同步)
- 操作权限 (接口访问控制)
-
常见权限角色模型
2.1 RBAC 模型(Role-Based Access Control)
RBAC0模型- 权限系统主要由三个要素构成:帐号,角色,权限。
- RBAC1模型- 子角色 继承
- RBAC2模型- 增加了对角色的一些限制:角色互斥、基数约束、先决条件角色等
2.2 基于属性的权限验证(ABAC: Attribute-Based Access Control)
通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。
属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。
工单权限模块设计与实现
3.1 权限绑定(元数据表)
@ManyToOne(() => Employee)
@JoinColumn({
name: 'employee_id'
})
employee: Employee;
@Column({
name: 'meta_key',
comment: '元数据类型',
type: 'varchar',
length: 50,
nullable: false
})
metaKey: string;
@Column({
name: 'meta_value',
comment: '元数据值',
type: 'json',
nullable: false
})
metaValue: any;
3.2 权限更新(动态获取)
const cacheManager: Cache = nestApp.get(CACHE_MANAGER);
const permissions =
(await cacheManager.get(cacheKey)) ||
(await employeeService.getMetadata(currentUser.userid, 'permission').then(value => {
cacheManager.set(cacheKey, value || [], {
ttl: 60 * 3
});
return value;
}));
currentUser.permissions = permissions;
req.security = new SecurityStore(currentUser);
3.3 访问控制
- 通过路由守卫(页面、接口权限)
通过代码逻辑判断(hasPermisson) ```typescript export function RequireAuth( enable: boolean | PermissionEnum | PermissionEnum[] = true ): MethodDecorator & ClassDecorator { return (target: object, key?: any, descriptor?: any) => {
if (key && descriptor?.value) {
Reflect.defineMetadata(AUTH_METADATA, enable, descriptor.value);
return descriptor;
}
Reflect.defineMetadata(AUTH_METADATA, enable, target);
return target;
}; }
if (authGuard) {
const ctx = context.switchToHttp();
const req = ctx.getRequest
// 检查是否存在登录token
if (!req.session.currentUser) {
throw new UnauthorizedException(i18n.__('抱歉,您需要先登录后才能继续操作'));
}
if (
typeof authGuard === 'string' &&
!req.security.hasPermission(authGuard as PermissionEnum) &&
!req.session.currentUser?.isAdmin
) {
throw new ForbiddenException(i18n.__('抱歉,您没有访问权限'));
}
存在问题
参考文档
角色权限设计的100种解法 | 人人都是产品经理
权限系统设计模型分析(DAC,MAC,RBAC,ABAC)
https://www.v2ex.com/t/416757