工单权限模块设计与问题

权限划分

  • 页面权限(按钮、菜单,权限更新同步)
  • 操作权限 (接口访问控制)
  • 数据权限(增删改查,范围,显示)

    常见权限角色模型

    2.1 RBAC 模型(Role-Based Access Control)

  • RBAC0模型- 权限系统主要由三个要素构成:帐号,角色,权限。

  • RBAC1模型- 子角色 继承
  • RBAC2模型- 增加了对角色的一些限制:角色互斥、基数约束、先决条件角色等

image.png

2.2 基于属性的权限验证(ABAC: Attribute-Based Access Control)

通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。
属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

工单权限模块设计与实现

3.1 权限绑定(元数据表)

  1. @ManyToOne(() => Employee)
  2. @JoinColumn({
  3. name: 'employee_id'
  4. })
  5. employee: Employee;
  6. @Column({
  7. name: 'meta_key',
  8. comment: '元数据类型',
  9. type: 'varchar',
  10. length: 50,
  11. nullable: false
  12. })
  13. metaKey: string;
  14. @Column({
  15. name: 'meta_value',
  16. comment: '元数据值',
  17. type: 'json',
  18. nullable: false
  19. })
  20. metaValue: any;

image.png

3.2 权限更新(动态获取)

  1. const cacheManager: Cache = nestApp.get(CACHE_MANAGER);
  2. const permissions =
  3. (await cacheManager.get(cacheKey)) ||
  4. (await employeeService.getMetadata(currentUser.userid, 'permission').then(value => {
  5. cacheManager.set(cacheKey, value || [], {
  6. ttl: 60 * 3
  7. });
  8. return value;
  9. }));
  10. currentUser.permissions = permissions;
  11. 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) => {

    1. if (key && descriptor?.value) {
    2. Reflect.defineMetadata(AUTH_METADATA, enable, descriptor.value);
    3. return descriptor;
    4. }
    5. Reflect.defineMetadata(AUTH_METADATA, enable, target);
    6. return target;

    }; }

if (authGuard) { const ctx = context.switchToHttp(); const req = ctx.getRequest(); const { i18n } = req.global;

  1. // 检查是否存在登录token
  2. if (!req.session.currentUser) {
  3. throw new UnauthorizedException(i18n.__('抱歉,您需要先登录后才能继续操作'));
  4. }
  5. if (
  6. typeof authGuard === 'string' &&
  7. !req.security.hasPermission(authGuard as PermissionEnum) &&
  8. !req.session.currentUser?.isAdmin
  9. ) {
  10. throw new ForbiddenException(i18n.__('抱歉,您没有访问权限'));
  11. }

} ```

存在问题

  • 用户组权限管理
  • 超级管理员权限管理
  • 权限修改更新

    后续优化

  • 将用户角色关系扩展到用户组

  • 优化权限实时更新

参考文档
角色权限设计的100种解法 | 人人都是产品经理
权限系统设计模型分析(DAC,MAC,RBAC,ABAC)
https://www.v2ex.com/t/416757