Modules

身份管理 (IAM)

身份与访问管理模块文档。

IAM (Identity and Access Management) 模块负责系统的用户认证、授权以及组织架构管理。

1. RBAC 权限模型

IAM 模块基于 RBAC (Role-Based Access Control) 模型设计,实现了细粒度的权限控制。

1.1 RBAC 模型概述

RBAC 是一种基于角色的访问控制模型,通过将权限分配给角色,再将角色分配给用户,实现了权限的集中管理和灵活分配。

核心思想

  • 用户 (User) 与角色 (Role) 多对多关联
  • 角色 (Role) 与权限 (Permission) 多对多关联
  • 权限 (Permission) 与资源 (Resource) 一一对应

1.2 权限类型

Tagtag Starter 的 RBAC 模型支持两种类型的权限:

1.2.1 功能权限

控制用户是否可以访问系统的某个功能或操作,包括:

  • 菜单访问权限
  • 按钮操作权限
  • API 接口权限

功能权限的标识格式为:{模块}:{资源}:{操作},例如:

  • sys:user:view - 查看用户
  • sys:user:add - 新增用户
  • sys:user:update - 更新用户
  • sys:user:delete - 删除用户

1.2.2 数据权限

控制用户可以访问的数据范围,包括:

  • 全部数据:可以访问所有数据
  • 本部门数据:只能访问所属部门的数据
  • 本部门及子部门数据:可以访问所属部门及其子部门的数据
  • 自定义数据:根据自定义规则过滤数据

1.3 权限继承

权限支持继承关系:

  • 目录权限继承:如果用户拥有某个目录的访问权限,默认拥有该目录下所有子菜单的访问权限
  • 角色权限继承:可以创建角色层级,子角色继承父角色的权限

2. 数据模型

2.1 用户 (User)

代表系统的操作员。

属性:

  • 用户名 (username)
  • 密码 (password,BCrypt加密)
  • 姓名 (name)
  • 邮箱 (email)
  • 电话 (phone)
  • 状态 (status: 1-启用, 0-禁用)
  • 归属部门 (dept_id)
  • 创建时间 (create_time)
  • 更新时间 (update_time)

关联:

  • 一个用户可以拥有多个角色 (多对多关系)
  • 一个用户属于一个部门 (多对一关系)

2.2 角色 (Role)

代表一组权限的集合。

属性:

  • 角色名称 (name)
  • 角色编码 (code)
  • 状态 (status: 1-启用, 0-禁用)
  • 数据权限类型 (data_scope_type)
  • 描述 (description)

功能:

  • 用于批量分配权限给用户
  • 可以配置角色的数据访问范围
  • 支持角色层级,实现权限继承

2.3 权限/菜单 (Permission/Menu)

代表系统中的功能资源。

属性:

  • 权限名称 (name)
  • 权限编码 (code)
  • 权限类型 (type: 1-目录, 2-菜单, 3-按钮)
  • 父级ID (parent_id)
  • 路由路径 (path)
  • 组件路径 (component)
  • 图标 (icon)
  • 排序 (sort)
  • 状态 (status: 1-启用, 0-禁用)

类型:

  • 目录 (Directory): 左侧菜单栏的分组,不对应具体页面
  • 菜单 (Menu): 具体的页面入口,对应一个路由
  • 按钮 (Button): 页面内的功能操作,对应一个权限标识

标识: 如 sys:user:add,用于后端接口权限校验和前端按钮显示控制。

2.4 部门 (Dept)

代表企业的组织层级结构。

属性:

  • 部门名称 (name)
  • 部门编码 (code)
  • 父级ID (parent_id)
  • 排序 (sort)
  • 状态 (status: 1-启用, 0-禁用)

结构: 树形结构,支持无限层级。

用途: 用于构建组织架构树,以及作为数据权限的判定依据。

2.5 关系表

  • user_role: 用户与角色的多对多关系表
  • role_permission: 角色与权限的多对多关系表

3. 核心功能实现

3.1 用户管理

功能: 用户的增删改查、密码重置、状态变更、角色分配。

实现细节:

  • 密码加密:使用 BCrypt 算法进行密码加密,确保密码安全
  • 用户状态控制:禁用用户无法登录系统
  • 角色分配:支持为用户分配多个角色
  • 数据权限:根据用户所属部门和角色数据权限配置,控制用户可访问的数据范围

3.2 角色管理

功能: 角色的创建与维护、权限分配、数据权限配置。

实现细节:

  • 权限分配:通过树形选择器勾选菜单和按钮权限
  • 数据权限配置:支持配置角色的数据访问范围
  • 角色状态控制:禁用角色的权限对用户无效

3.3 菜单管理

功能: 可视化管理系统的菜单结构、配置菜单属性、定义按钮权限。

实现细节:

  • 树形结构:支持无限层级菜单
  • 路由配置:自动生成前端路由配置
  • 组件路径:配置页面组件路径
  • 权限标识:定义按钮权限标识,用于前端按钮控制

3.4 部门管理

功能: 维护企业的组织架构树。

实现细节:

  • 树形结构:支持无限层级部门
  • 部门编码:自动生成部门编码,支持自定义编码规则
  • 部门状态:禁用部门下的用户无法登录系统

4. 权限校验流程

4.1 后端权限校验

流程:

  1. 用户登录系统,获取 JWT 令牌
  2. 请求 API 时,在请求头中携带 JWT 令牌
  3. 后端拦截器验证 JWT 令牌的有效性
  4. 权限守卫 @PreAuthorize 检查用户是否拥有该 API 的访问权限
  5. 如果用户没有权限,返回 403 Forbidden 响应

实现方式:

@RestController
@RequestMapping("/users")
public class UserController {
    
    @PostMapping
    @PreAuthorize("@ss.hasPermission('sys:user:add')")
    public Result<Void> addUser(@RequestBody @Validated UserDTO userDTO) {
        // 新增用户逻辑
    }
    
    @PutMapping
    @PreAuthorize("@ss.hasPermission('sys:user:update')")
    public Result<Void> updateUser(@RequestBody @Validated UserDTO userDTO) {
        // 更新用户逻辑
    }
}

权限守卫实现:

@Component("ss")
public class PermissionGuard {
    
    public boolean hasPermission(String permission) {
        // 1. 获取当前用户
        UserPrincipal user = AuthContext.getCurrentUser();
        
        // 2. 检查用户是否为超级管理员
        if (user.isSuperAdmin()) {
            return true;
        }
        
        // 3. 检查用户是否拥有该权限
        return user.getPermissions().contains(permission);
    }
}

4.2 前端权限控制

流程:

  1. 用户登录成功后,获取用户的菜单列表和权限列表
  2. 根据菜单列表动态生成左侧菜单栏
  3. 根据权限列表控制页面按钮的显示/隐藏

实现方式:

4.2.1 菜单权限控制

// 获取用户菜单
const menuList = await getMenuList();
// 动态生成路由
const routes = generateRoutes(menuList);
// 添加到路由表
routes.forEach(route => router.addRoute(route));

4.2.2 按钮权限控制

使用 v-auth 指令控制按钮显示:

<template>
  <button v-auth="'sys:user:add'">新增用户</button>
  <button v-auth="'sys:user:delete'">删除用户</button>
</template>

或者使用 AccessControl 组件:

<template>
  <AccessControl :access="'sys:user:add'">
    <button>新增用户</button>
  </AccessControl>
</template>

权限指令实现:

export const AuthDirective = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    const permission = binding.value;
    // 检查用户是否拥有该权限
    if (!useAccess().hasPermission(permission)) {
      el.style.display = 'none';
    }
  }
};

5. 核心代码结构

5.1 后端代码结构

tagtag-module-iam
└── src
    └── main
        ├── java
        │   └── dev
        │       └── tagtag
        │           └── module
        │               └── iam
        │                   ├── controller
        │                   │   ├── DeptController.java
        │                   │   ├── MenuController.java
        │                   │   ├── RoleController.java
        │                   │   └── UserController.java
        │                   ├── entity
        │                   │   ├── DeptEntity.java
        │                   │   ├── MenuEntity.java
        │                   │   ├── RoleEntity.java
        │                   │   ├── UserEntity.java
        │                   │   ├── UserRoleEntity.java
        │                   │   └── RolePermissionEntity.java
        │                   ├── mapper
        │                   │   ├── DeptMapper.java
        │                   │   ├── MenuMapper.java
        │                   │   ├── RoleMapper.java
        │                   │   ├── UserMapper.java
        │                   │   ├── UserRoleMapper.java
        │                   │   └── RolePermissionMapper.java
        │                   ├── service
        │                   │   ├── DeptService.java
        │                   │   ├── MenuService.java
        │                   │   ├── RoleService.java
        │                   │   └── UserService.java
        │                   └── util
        │                       └── DataPermissionUtil.java
        └── resources
            ├── db
            │   ├── schema.sql
            │   └── data
            │       ├── 00_iam_dept.sql
            │       ├── 01_iam_role.sql
            │       ├── 02_iam_user.sql
            │       ├── 03_iam_menu.sql
            │       ├── 04_iam_user_role.sql
            │       └── 05_iam_role_menu.sql
            └── mapper
                └── iam
                    ├── DeptMapper.xml
                    ├── MenuMapper.xml
                    ├── RoleMapper.xml
                    └── UserMapper.xml

5.2 前端代码结构

frontend/apps/tagtag/src/views/modules/iam
├── dept
│   ├── data.ts
│   └── index.vue
├── menu
│   ├── FormModal.vue
│   ├── data.ts
│   └── index.vue
├── role
│   ├── data.ts
│   └── index.vue
└── user
    ├── DeptTree.vue
    ├── data.ts
    └── index.vue

6. 前端实现

前端相关代码位于 frontend/apps/tagtag/src/views/modules/iam

功能页面路径描述
用户管理/iam/user用户列表、新增/编辑弹窗
角色管理/iam/role角色列表、权限分配抽屉
菜单管理/iam/menu菜单树形表格、图标选择
部门管理/iam/dept部门树形维护

7. API 参考

方法端点描述
POST/auth/login用户登录 (返回 JWT)
GET/menus/routes获取当前用户的动态路由
GET/menus/tree获取菜单树形结构
GET/users获取用户列表
POST/users创建新用户
PUT/users更新用户信息
DELETE/users删除用户
GET/roles获取角色列表
POST/roles创建新角色
PUT/roles更新角色信息
DELETE/roles删除角色
GET/roles/permissions获取角色权限
POST/roles/permissions分配角色权限
GET/depts/tree获取部门树形结构
POST/depts创建新部门
PUT/depts更新部门信息
DELETE/depts删除部门

8. 最佳实践

8.1 权限设计

  • 最小权限原则: 只授予用户完成工作所需的最小权限
  • 权限分组: 按功能模块分组权限,便于管理和分配
  • 命名规范: 权限标识使用统一的命名规范,如 {模块}:{资源}:{操作}
  • 数据权限: 根据业务需求合理配置角色的数据权限

8.2 角色设计

  • 角色分层: 创建不同层级的角色,如超级管理员、管理员、普通用户
  • 职责分离: 不同角色负责不同的功能模块
  • 角色复用: 避免为每个用户创建专用角色,尽量复用现有角色

8.3 菜单设计

  • 合理分类: 按功能模块分类菜单,便于用户导航
  • 层级适中: 菜单层级不宜过深,建议不超过 3 层
  • 权限关联: 每个菜单和按钮都应关联相应的权限标识
  • 默认展开: 合理设置默认展开的菜单,提高用户体验

8.4 部门设计

  • 清晰层级: 部门层级应清晰反映企业的组织架构
  • 编码规范: 使用统一的部门编码规则
  • 状态管理: 及时更新部门状态,禁用不需要的部门

9. 扩展建议

9.1 支持多租户

如果系统需要支持多租户,可以在 IAM 模块中添加租户管理功能:

  • 新增租户实体
  • 为用户和部门添加租户属性
  • 实现租户隔离

9.2 支持第三方登录

集成第三方登录,如 OAuth 2.0、LDAP 等:

  • 添加第三方登录配置
  • 实现第三方登录回调处理
  • 关联第三方用户与系统用户

9.3 支持细粒度数据权限

实现更细粒度的数据权限控制:

  • 支持基于字段的数据权限
  • 支持基于条件的数据权限
  • 支持自定义数据权限规则

9.4 支持权限审计

添加权限审计功能,记录用户的权限变更历史:

  • 记录用户角色变更
  • 记录角色权限变更
  • 生成权限审计报告

10. 总结

IAM 模块是 Tagtag Starter 系统的核心模块之一,负责系统的用户认证、授权以及组织架构管理。基于 RBAC 模型设计,实现了细粒度的权限控制,包括功能权限和数据权限。

通过 IAM 模块,管理员可以方便地管理用户、角色、菜单和部门,实现了权限的集中管理和灵活分配。同时,系统提供了完善的权限校验机制,确保只有授权用户才能访问系统资源。

IAM 模块的设计和实现遵循了模块化、可扩展的原则,便于后续功能扩展和定制化开发。