权限划分
- 页面权限(按钮、菜单,权限更新同步)
- 操作权限 (接口访问控制)
-
常见权限角色模型
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
// 检查是否存在登录tokenif (!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
