工厂权限管理系统方案

一、需求概述

1.1 组织结构层级

工厂采用四级层级结构:

工厂 (Factory)
  └── 工场 (Workshop)
      └── 产线 (Production Line)
          └── 工程 (Project)

1.2 核心需求

  1. 层级继承:上层负责人自动获得下层所有权限
  2. 角色区分:每个层级包含负责人和普通用户
  3. 页面权限:不同角色访问不同页面
  4. 数据权限:同一页面内,不同用户看到的数据范围不同

二、权限模型设计

2.1 RBAC + 数据权限模型

采用 RBAC(Role-Based Access Control) 结合 数据权限(Data Scope) 的混合模型。

用户 (User)
  ↓ 拥有
角色 (Role)
  ↓ 关联
权限 (Permission)
  ├── 功能权限 (Function Permission) - 页面/菜单/按钮
  └── 数据权限 (Data Permission) - 数据范围

2.2 角色定义

系统角色

角色代码角色名称层级说明
FACTORY_ADMIN工厂管理员工厂可管理整个工厂
FACTORY_USER工厂普通用户工厂仅访问工厂层级数据
WORKSHOP_ADMIN工场负责人工场可管理所属工场及下级
WORKSHOP_USER工场普通用户工场仅访问所属工场数据
LINE_ADMIN产线负责人产线可管理所属产线及下级
LINE_USER产线普通用户产线仅访问所属产线数据
PROJECT_ADMIN工程负责人工程可管理所属工程
PROJECT_USER工程普通用户工程仅访问所属工程数据

三、权限模型方案对比

在选择具体实现方案前,让我们先对比几种主流权限模型的优缺点。

3.1 主流权限模型对比

ACL (Access Control List) - 访问控制列表

定义:最简单的权限模型,直接为用户分配资源访问权限,维护一个用户和权限的映射列表。

优点:

  • ✅ 简单直接,易于理解和实现
  • ✅ 适合小型系统和简单权限场景
  • ✅ 开发成本低,快速上线

缺点:

  • ❌ 权限控制分散,不便于管理
  • ❌ 无法简单地将一组资源统一授权给一群用户
  • ❌ 用户数量增加时维护成本呈指数增长
  • ❌ 权限变更需要逐个修改用户权限

适用场景:用户少于 50 人的小型系统,权限结构简单不经常变化


RBAC (Role-Based Access Control) - 基于角色的访问控制

定义:通过角色作为中间层,用户获得角色,角色拥有权限,实现用户与权限的解耦。

优点:

  • ✅ 构建简单,易用性高,配置便捷
  • ✅ 权限管理集中,修改角色权限即可影响所有该角色用户
  • ✅ 对于大型组织具有良好的可扩展性
  • ✅ 符合企业组织架构,易于理解和推广
  • ✅ 支持角色继承(RBAC1),实现层级权限

缺点:

  • ❌ 无法做到资源细粒度授权(只能授权某类资源,不能授权特定资源实例)
  • ❌ 无法表达复杂的动态权限规则(如”只能删除自己创建的且状态为草稿的数据”)
  • ❌ 角色数量可能随业务增长而膨胀(角色爆炸问题)

适用场景:✅ 工厂层级管理系统(本方案推荐) - 组织结构清晰,权限相对固定


ABAC (Attribute-Based Access Control) - 基于属性的访问控制

定义:通过评估用户属性、资源属性、环境属性和操作属性的组合来动态判断权限。

示例规则:

// 允许访问条件:
user.department == resource.department &&
user.level >= 3 &&
currentTime.hour >= 9 && currentTime.hour <= 18 &&
resource.confidentialLevel <= user.clearanceLevel

优点:

  • ✅ 权限粒度极细,可以控制到具体资源实例和字段
  • ✅ 支持复杂的动态权限逻辑
  • ✅ 不需要预定义所有权限组合,减轻维护成本
  • ✅ 高度灵活,适应复杂多变的业务场景

缺点:

  • ❌ 模型复杂,学习成本高,开发难度大
  • ❌ 权限规则不直观,难以追溯用户实际拥有的权限
  • ❌ 规则复杂时性能开销大(需要实时评估多个属性)
  • ❌ 规则维护困难,容易出现冲突或遗漏

适用场景:需要高度动态权限控制的场景(如多租户 SaaS 平台、医疗系统、政务系统)


混合模型:RBAC + 数据权限(本方案采用)

设计思路:

  • 使用 RBAC 管理功能权限(页面、菜单、按钮)
  • 使用 数据范围(Data Scope) 管理数据权限(行级数据过滤)
  • 可选引入 ABAC 规则引擎 处理特殊业务场景

优势分析:

  • ✅ 兼顾简单性和灵活性
  • ✅ 功能权限通过角色管理,易于配置
  • ✅ 数据权限通过组织层级自动过滤,无需逐条配置
  • ✅ 满足 90% 的企业权限需求
  • ✅ 可按需扩展 ABAC 规则处理剩余 10% 的复杂场景

适用场景:✅ 强烈推荐用于本工厂权限系统


3.2 数据权限实现方案对比

方案一:SQL 拼接(本方案采用)

实现方式:通过 AOP 拦截查询方法,根据用户角色动态拼接 WHERE 条件。

-- 原始 SQL
SELECT * FROM productions WHERE status = 'ACTIVE'
 
-- 工场管理员访问时自动拼接
SELECT * FROM productions
WHERE status = 'ACTIVE' AND workshop_id = 1

优点:

  • ✅ 实现简单,侵入性小
  • ✅ 性能好,在数据库层面过滤
  • ✅ 适用于所有 ORM 框架
  • ✅ 不需要修改业务 SQL

缺点:

  • ❌ 需要表结构包含组织字段(factory_id, workshop_id 等)
  • ❌ 复杂 JOIN 查询需要仔细处理别名

方案二:视图隔离

实现方式:为不同角色创建数据库视图,用户只能访问自己的视图。

-- 工场管理员视图
CREATE VIEW workshop_1_productions AS
SELECT * FROM productions WHERE workshop_id = 1;
 
-- 授权
GRANT SELECT ON workshop_1_productions TO workshop_admin_role;

优点:

  • ✅ 数据库层面的强制隔离,安全性高
  • ✅ 应用代码无需关心权限逻辑

缺点:

  • ❌ 视图数量会随组织增长而膨胀
  • ❌ 权限变更需要修改视图定义
  • ❌ 维护成本高,不适合动态组织结构

方案三:应用层过滤

实现方式:查询所有数据后在应用内存中过滤。

List<Production> all = productionRepository.findAll();
return all.stream()
    .filter(p -> p.getWorkshopId().equals(currentUser.getWorkshopId()))
    .collect(Collectors.toList());

优点:

  • ✅ 实现灵活,可以处理复杂逻辑
  • ✅ 不依赖数据库特性

缺点:

  • ❌ 性能极差,需要加载全量数据到内存
  • ❌ 无法利用数据库索引
  • ❌ 数据量大时可能 OOM
  • ❌ 不推荐使用

方案四:行级安全策略(Row-Level Security)

实现方式:使用数据库原生的 RLS 功能(PostgreSQL、Oracle 支持)。

-- PostgreSQL 示例
CREATE POLICY workshop_policy ON productions
FOR SELECT
USING (workshop_id = current_setting('app.current_workshop_id')::bigint);
 
ALTER TABLE productions ENABLE ROW LEVEL SECURITY;

优点:

  • ✅ 数据库原生支持,安全性最高
  • ✅ 性能优秀,在执行计划层面优化
  • ✅ 应用代码完全无感知

缺点:

  • ❌ 依赖特定数据库(MySQL 不支持)
  • ❌ 需要传递用户上下文到数据库连接
  • ❌ 调试困难,权限问题不易排查

3.3 方案选型建议

维度ACLRBACABACRBAC+数据权限
实现复杂度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
维护成本⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
权限粒度粗中细中-细
性能开销低低高中
适合场景小型系统企业管理系统复杂多变场景工厂层级系统
学习曲线平缓平缓陡峭中等

本方案推荐:RBAC + 数据权限(SQL 拼接)

理由:

  1. ✅ 工厂组织结构清晰稳定,适合 RBAC
  2. ✅ 层级继承需求通过数据范围完美实现
  3. ✅ 性能和复杂度平衡最优
  4. ✅ 团队学习成本可控
  5. ✅ 可按需扩展 ABAC 规则引擎

四、数据权限范围(Data Scope)

4.1 数据范围类型

范围代码范围名称描述适用角色
ALL全部数据可查看所有层级数据超级管理员
FACTORY工厂数据当前工厂及下级所有数据FACTORY_ADMIN
WORKSHOP工场数据当前工场及下级所有数据WORKSHOP_ADMIN
LINE产线数据当前产线及下级所有数据LINE_ADMIN
PROJECT工程数据仅当前工程数据PROJECT_ADMIN
SELF个人数据仅自己创建/负责的数据所有普通用户

4.2 层级继承规则

# 伪代码示例
def get_accessible_data(user):
    if user.role == 'FACTORY_ADMIN':
        return query.filter(factory_id == user.factory_id)
    elif user.role == 'WORKSHOP_ADMIN':
        return query.filter(workshop_id == user.workshop_id)
    elif user.role == 'LINE_ADMIN':
        return query.filter(line_id == user.line_id)
    elif user.role == 'PROJECT_ADMIN':
        return query.filter(project_id == user.project_id)
    else:  # 普通用户
        return query.filter(created_by == user.id)

五、功能权限设计

5.1 权限表设计

Permission 表

CREATE TABLE permissions (
    id BIGINT PRIMARY KEY,
    code VARCHAR(100) UNIQUE,       -- 权限代码,如 'factory:view'
    name VARCHAR(100),               -- 权限名称
    type ENUM('MENU', 'BUTTON', 'API'), -- 权限类型
    parent_id BIGINT,                -- 父权限(用于菜单树)
    path VARCHAR(200),               -- 前端路由路径
    component VARCHAR(200),          -- 前端组件路径
    icon VARCHAR(50),                -- 图标
    sort_order INT,                  -- 排序
    status TINYINT DEFAULT 1         -- 状态(0停用 1启用)
);

Role 表

CREATE TABLE roles (
    id BIGINT PRIMARY KEY,
    code VARCHAR(50) UNIQUE,         -- 角色代码
    name VARCHAR(100),               -- 角色名称
    level ENUM('FACTORY', 'WORKSHOP', 'LINE', 'PROJECT'), -- 层级
    data_scope ENUM('ALL', 'FACTORY', 'WORKSHOP', 'LINE', 'PROJECT', 'SELF'),
    description TEXT,
    status TINYINT DEFAULT 1
);

RolePermission 关联表

CREATE TABLE role_permissions (
    role_id BIGINT,
    permission_id BIGINT,
    PRIMARY KEY (role_id, permission_id)
);

User 表

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    username VARCHAR(50) UNIQUE,
    password VARCHAR(200),
    real_name VARCHAR(100),
    factory_id BIGINT,               -- 所属工厂
    workshop_id BIGINT,              -- 所属工场
    line_id BIGINT,                  -- 所属产线
    project_id BIGINT,               -- 所属工程
    status TINYINT DEFAULT 1
);

UserRole 关联表

CREATE TABLE user_roles (
    user_id BIGINT,
    role_id BIGINT,
    PRIMARY KEY (user_id, role_id)
);

六、技术框架对比

在实现权限系统时,选择合适的技术框架至关重要。以下对比几种主流 Java 权限框架。

6.1 主流权限框架对比

Spring Security

简介:Spring 生态圈的官方安全框架,与 Spring Boot 深度集成。

优点:

  • ✅ Spring 官方支持,文档完善,社区活跃
  • ✅ 与 Spring Boot 无缝集成,开箱即用
  • ✅ 功能全面:认证、授权、OAuth2、CSRF 防护等
  • ✅ 支持多种认证方式(Form、OAuth2、LDAP、JWT 等)
  • ✅ 安全更新及时,漏洞修复快速

缺点:

  • ❌ 配置复杂,学习曲线陡峭
  • ❌ 过滤器链较重,性能开销相对较大(约 0.116ms)
  • ❌ 定制化需要深入理解框架机制
  • ❌ 对于简单项目显得”重量级”

性能数据:

  • 无权限框架基准:0ms
  • Spring Security 损耗:0.116ms

适用场景:Spring 生态的中大型企业应用,需要完整安全解决方案


Apache Shiro

简介:轻量级的 Java 安全框架,可独立于 Spring 使用。

优点:

  • ✅ 简单易用,API 设计直观,学习成本低
  • ✅ 轻量级,性能优于 Spring Security(约 0.088ms)
  • ✅ 可独立使用,不依赖 Spring
  • ✅ 插件式架构,易于扩展
  • ✅ 支持多种认证和授权机制

缺点:

  • ❌ 社区活跃度不如 Spring Security
  • ❌ 功能相对较少(如缺少 OAuth2 原生支持)
  • ❌ 更新频率较慢
  • ❌ 与 Spring Boot 集成需要额外配置

性能数据:

  • Shiro 损耗:0.088ms(比 Spring Security 快 30%)

适用场景:非 Spring 项目、对性能敏感的应用、简单的认证授权需求


Casbin (jCasbin)

简介:跨语言的权限管理库,专注于访问控制模型(ACL、RBAC、ABAC)。

优点:

  • ✅ 专注权限控制,支持多种模型(ACL、RBAC、ABAC、RESTful 等)
  • ✅ 策略定义灵活,使用 DSL 描述权限规则
  • ✅ 轻量级,易于集成到现有项目
  • ✅ 跨语言支持(Go、Java、Python、Node.js 等)
  • ✅ 可与 Spring Security/Shiro 结合使用

缺点:

  • ❌ 仅提供授权功能,不包含认证
  • ❌ 需要自行实现认证和会话管理
  • ❌ 中文文档较少
  • ❌ 国内案例相对较少

策略示例:

# RBAC 模型定义
[request_definition]
r = sub, obj, act
 
[policy_definition]
p = sub, obj, act
 
[role_definition]
g = _, _
 
[policy_effect]
e = some(where (p.eft == allow))
 
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

适用场景:需要复杂权限模型(ABAC)、微服务架构、多语言技术栈


Sa-Token(新兴国产框架)

简介:国产轻量级 Java 权限认证框架,简化权限管理。

优点:

  • ✅ 轻量级,性能最优(约 0.026ms 损耗)
  • ✅ API 简洁优雅,易于上手
  • ✅ 功能全面:登录认证、权限验证、SSO、OAuth2、微服务网关鉴权
  • ✅ 中文文档完善,国内社区活跃
  • ✅ 支持多种集成方式(Spring Boot、Servlet、WebFlux)

缺点:

  • ❌ 相对新兴,企业级案例积累不足
  • ❌ 国际化支持较弱
  • ❌ 生态不如 Spring Security 完善

性能数据:

  • Sa-Token 损耗:0.026ms(性能最优)

适用场景:国内项目、需要快速开发、性能敏感型应用


6.2 框架选型对比表

维度Spring SecurityApache ShiroCasbinSa-Token
学习曲线陡峭平缓中等平缓
性能损耗0.116ms0.088ms-0.026ms
功能完整性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Spring 集成原生需配置需配置良好
社区活跃度极高中中高(国内)
文档质量优秀(英文)良好一般优秀(中文)
认证支持✅✅❌✅
授权模型RBACRBACACL/RBAC/ABACRBAC
OAuth2 支持✅ 原生❌ 需插件❌✅
分布式会话✅✅❌✅
推荐指数⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

6.3 本方案推荐

主框架:Spring Security + Casbin(可选)

推荐理由:

  1. ✅ Spring Boot 项目,Spring Security 集成最自然
  2. ✅ 完整的认证授权解决方案,降低开发成本
  3. ✅ 企业级安全保障,满足合规要求
  4. ✅ 对于复杂权限规则,可引入 Casbin 作为策略引擎

替代方案:

  • Sa-Token:如果团队对 Spring Security 学习成本有顾虑,且追求性能
  • Shiro + Casbin:非 Spring 项目或需要轻量级方案

6.4 数据库选型建议

数据库行级安全策略递归查询推荐度
PostgreSQL✅ 原生 RLS✅ WITH RECURSIVE⭐⭐⭐⭐⭐
MySQL❌ 不支持✅ (8.0+)⭐⭐⭐⭐
Oracle✅ VPD✅ CONNECT BY⭐⭐⭐⭐⭐
SQL Server✅ RLS✅ CTE⭐⭐⭐⭐

本方案推荐:MySQL 8.0+(考虑通用性和团队熟悉度)


七、技术实现方案

7.1 后端实现(以 Spring Boot + MyBatis-Plus 为例)

自定义数据权限注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataScope {
    /**
     * 组织表的别名
     */
    String factoryAlias() default "";
    String workshopAlias() default "";
    String lineAlias() default "";
    String projectAlias() default "";
}

AOP 拦截器

@Aspect
@Component
public class DataScopeAspect {
 
    @Before("@annotation(dataScope)")
    public void doBefore(JoinPoint point, DataScope dataScope) {
        User currentUser = SecurityUtils.getCurrentUser();
 
        // 构建数据权限 SQL 片段
        String sqlFilter = buildDataScopeFilter(currentUser, dataScope);
 
        // 设置到 ThreadLocal,供 MyBatis 拦截器使用
        DataScopeContext.setSqlFilter(sqlFilter);
    }
 
    private String buildDataScopeFilter(User user, DataScope dataScope) {
        String filter = "";
        String dataScope = user.getRole().getDataScope();
 
        switch (dataScope) {
            case "FACTORY":
                filter = dataScope.factoryAlias() + ".id = " + user.getFactoryId();
                break;
            case "WORKSHOP":
                filter = dataScope.workshopAlias() + ".id = " + user.getWorkshopId();
                break;
            case "LINE":
                filter = dataScope.lineAlias() + ".id = " + user.getLineId();
                break;
            case "PROJECT":
                filter = dataScope.projectAlias() + ".id = " + user.getProjectId();
                break;
            case "SELF":
                filter = "created_by = " + user.getId();
                break;
        }
 
        return filter;
    }
}

Controller 使用示例

@RestController
@RequestMapping("/api/production")
public class ProductionController {
 
    @GetMapping("/list")
    @PreAuthorize("hasPermission('production:view')")
    @DataScope(factoryAlias = "f", workshopAlias = "w", lineAlias = "l")
    public List<Production> list() {
        // 查询会自动应用数据权限过滤
        return productionService.list();
    }
}

7.2 前端实现(Vue 3 示例)

路由权限控制

// router/index.js
router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();
 
  if (!userStore.permissions.includes(to.meta.permission)) {
    next({ name: '403' }); // 无权限页面
    return;
  }
 
  next();
});

按钮级权限指令

// directives/permission.js
export default {
  mounted(el, binding) {
    const { value } = binding;
    const permissions = store.state.user.permissions;
 
    if (value && !permissions.includes(value)) {
      el.parentNode?.removeChild(el);
    }
  }
};
 
// 使用
<button v-permission="'production:create'">新建生产单</button>

八、权限配置示例

8.1 角色权限配置

工厂管理员权限

{
  "roleCode": "FACTORY_ADMIN",
  "dataScope": "FACTORY",
  "permissions": [
    "factory:view",
    "factory:create",
    "factory:edit",
    "factory:delete",
    "workshop:view",
    "workshop:create",
    "workshop:edit",
    "workshop:delete",
    "line:*",
    "project:*",
    "user:manage",
    "role:manage"
  ]
}

产线负责人权限

{
  "roleCode": "LINE_ADMIN",
  "dataScope": "LINE",
  "permissions": [
    "line:view",
    "line:edit",
    "project:view",
    "project:create",
    "project:edit",
    "project:delete",
    "production:view",
    "production:create",
    "quality:view",
    "quality:record"
  ]
}

普通用户权限

{
  "roleCode": "PROJECT_USER",
  "dataScope": "SELF",
  "permissions": [
    "project:view",
    "production:view",
    "task:view",
    "task:update"
  ]
}

九、最佳实践

9.1 权限设计原则

  1. 最小权限原则:默认无权限,显式授予
  2. 职责分离:管理权限与业务权限分离
  3. 层级继承:通过数据范围自动继承,无需重复配置
  4. 动态调整:支持运行时修改权限无需重启

9.2 性能优化

权限缓存策略

@Cacheable(value = "user:permissions", key = "#userId")
public Set<String> getUserPermissions(Long userId) {
    // 查询用户权限
    return permissionService.getByUserId(userId);
}

SQL 优化

-- 使用 CTE 优化层级查询
WITH RECURSIVE org_tree AS (
    SELECT id, parent_id, level
    FROM organizations
    WHERE id = :currentOrgId
 
    UNION ALL
 
    SELECT o.id, o.parent_id, o.level
    FROM organizations o
    INNER JOIN org_tree ot ON o.parent_id = ot.id
)
SELECT * FROM productions
WHERE org_id IN (SELECT id FROM org_tree);

9.3 安全考虑

  1. 防止越权访问

    // 检查用户是否有权访问该资源
    if (!hasAccessToResource(user, resourceId)) {
        throw new AccessDeniedException();
    }
  2. 敏感操作二次验证

    @PostMapping("/delete")
    @RequirePasswordConfirm  // 删除操作需要密码确认
    public void delete(Long id) {
        // ...
    }
  3. 审计日志

    @AfterReturning("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void logAccess(JoinPoint point) {
        auditService.log(
            user = currentUser,
            action = point.getSignature(),
            result = "SUCCESS"
        );
    }

十、扩展方案

10.1 动态权限规则引擎

使用规则引擎(如 Drools)支持复杂权限逻辑:

rule "Workshop Admin can access subordinate data"
when
    $user: User(role == "WORKSHOP_ADMIN")
    $resource: Resource(workshopId == $user.workshopId ||
                       workshop.parentId == $user.workshopId)
then
    grantAccess($user, $resource);
end

10.2 临时授权

支持临时提升权限:

@Service
public class TemporaryAuthService {
 
    public void grantTemporaryAccess(Long userId, String permission, Duration duration) {
        TemporaryAuth auth = new TemporaryAuth();
        auth.setUserId(userId);
        auth.setPermission(permission);
        auth.setExpireAt(LocalDateTime.now().plus(duration));
 
        temporaryAuthRepository.save(auth);
 
        // 刷新缓存
        permissionCache.evict(userId);
    }
}

10.3 字段级权限

对敏感字段进行脱敏或隐藏:

@JsonSerialize(using = SensitiveDataSerializer.class)
@SensitiveField(roles = {"FACTORY_ADMIN"})
private String employeeSalary;

十一、测试方案

11.1 权限测试用例

@Test
public void testWorkshopAdminCanAccessSubordinateData() {
    // Given: 工场管理员
    User workshopAdmin = createUser("WORKSHOP_ADMIN", workshopId = 1);
 
    // When: 查询产线数据
    List<Line> lines = lineService.list();
 
    // Then: 应该包含该工场下所有产线
    assertTrue(lines.stream()
        .allMatch(line -> line.getWorkshopId() == 1));
}
 
@Test
public void testLineUserCannotAccessOtherLineData() {
    // Given: 产线普通用户
    User lineUser = createUser("LINE_USER", lineId = 1);
 
    // When: 尝试查询其他产线数据
    assertThrows(AccessDeniedException.class, () -> {
        lineService.getById(2); // 产线 2 不属于该用户
    });
}

十二、总结

12.1 方案优势

✅ 清晰的层级模型:四级组织结构明确 ✅ 灵活的权限控制:功能权限 + 数据权限双重保障 ✅ 自动权限继承:上级自动获得下级权限 ✅ 易于扩展:支持动态规则、临时授权等高级特性 ✅ 性能优化:缓存 + SQL 优化

12.2 实施建议

  1. 第一阶段:实现基础 RBAC + 数据范围
  2. 第二阶段:添加前端权限控制 + 审计日志
  3. 第三阶段:引入规则引擎 + 临时授权
  4. 持续优化:根据实际使用情况调整权限粒度

附录

A. 相关技术栈

  • 后端框架:Spring Boot + Spring Security
  • ORM:MyBatis-Plus(支持数据权限插件)
  • 缓存:Redis
  • 前端:Vue 3 + Vue Router
  • 规则引擎:Drools(可选)

B. 参考资料

权限模型理论:

数据权限实践:

技术框架对比:

企业级实践:

官方文档:


标签: 权限管理 rbac 数据权限 系统设计 工厂管理