一、权限模型概述
权限系统是应用安全的基础:
权限模型:
- DAC(自主访问控制)
- MAC(强制访问控制)
- RBAC(基于角色的访问控制)
- ABAC(基于属性的访问控制)
二、RBAC模型
1. RBAC核心概念
用户 → 角色 → 权限 │ │ │ └── 权限(功能操作) │ └── 角色(职责集合)2. RBAC数据库设计
-- 用户表CREATETABLEsys_user(idBIGINTPRIMARYKEYAUTO_INCREMENT,usernameVARCHAR(50)NOTNULLUNIQUE,passwordVARCHAR(100)NOTNULL,nicknameVARCHAR(50),statusTINYINTDEFAULT1,create_timeTIMESTAMPDEFAULTCURRENT_TIMESTAMP);-- 角色表CREATETABLEsys_role(idBIGINTPRIMARYKEYAUTO_INCREMENT,role_codeVARCHAR(50)NOTNULLUNIQUE,role_nameVARCHAR(50)NOTNULL,descriptionVARCHAR(200),statusTINYINTDEFAULT1);-- 权限表CREATETABLEsys_permission(idBIGINTPRIMARYKEYAUTO_INCREMENT,perm_codeVARCHAR(100)NOTNULLUNIQUE,perm_nameVARCHAR(50)NOTNULL,resource_typeVARCHAR(20),-- menu, button, apiresource_pathVARCHAR(200),descriptionVARCHAR(200));-- 用户角色关联CREATETABLEsys_user_role(user_idBIGINT,role_idBIGINT,PRIMARYKEY(user_id,role_id));-- 角色权限关联CREATETABLEsys_role_permission(role_idBIGINT,permission_idBIGINT,PRIMARYKEY(role_id,permission_id));3. RBAC实现
@ServicepublicclassRbacService{// 获取用户权限publicSet<String>getUserPermissions(LonguserId){List<Permission>permissions=permissionMapper.selectByUserId(userId);returnpermissions.stream().map(Permission::getPermCode).collect(Collectors.toSet());}// 检查权限publicbooleanhasPermission(LonguserId,Stringpermission){Set<String>permissions=getUserPermissions(userId);returnpermissions.contains(permission);}// 权限注解@PreAuthorize("@rbacService.hasPermission(#userId, 'order:create')")publicOrdercreateOrder(LonguserId,OrderRequestrequest){// 创建订单returnorder;}}三、ABAC模型
1. ABAC核心概念
访问决策 = f(用户属性, 资源属性, 环境属性, 操作属性)属性类型:
- 用户属性:部门、职位、资历
- 资源属性:敏感等级、所有者
- 环境属性:时间、IP、地点
- 操作属性:读取、修改、删除
2. ABAC策略配置
{"policyId":"order-access-policy","description":"订单访问控制策略","subject":{"attributes":{"department":"string","position":"string"}},"resource":{"attributes":{"owner":"string","sensitivity":"string"}},"action":{"attributes":{"operation":["read","write","delete"]}},"rules":[{"effect":"permit","condition":{"and":[{"==":[{"var":"resource.owner"},{"var":"subject.userId"}]},{"==":[{"var":"action.operation"},"read"]}]}},{"effect":"permit","condition":{"and":[{"==":[{"var":"subject.position"},"manager"]},{"==":[{"var":"resource.sensitivity"},"normal"]}]}}]}3. ABAC实现
@ServicepublicclassAbacService{@AutowiredprivatePolicyRepositorypolicyRepository;publicbooleanevaluate(Subjectsubject,Resourceresource,Actionaction){// 加载匹配的策略List<Policy>policies=policyRepository.findMatchingPolicies(subject,resource,action);for(Policypolicy:policies){if(evaluatePolicy(policy,subject,resource,action)){returnpolicy.getEffect()==PolicyEffect.PERMIT;}}// 默认拒绝returnfalse;}privatebooleanevaluatePolicy(Policypolicy,Subjectsubject,Resourceresource,Actionaction){for(Rulerule:policy.getRules()){if(!evaluateRule(rule,subject,resource,action)){returnfalse;}}returntrue;}privatebooleanevaluateRule(Rulerule,Subjectsubject,Resourceresource,Actionaction){Conditioncondition=rule.getCondition();returnevaluateCondition(condition,subject,resource,action);}}四、RBAC vs ABAC对比
| 维度 | RBAC | ABAC |
|---|---|---|
| 复杂度 | 低 | 高 |
| 灵活性 | 低 | 高 |
| 维护成本 | 低 | 高 |
| 粒度 | 角色级 | 属性级 |
| 适用场景 | 固定角色 | 复杂权限 |
五、权限系统设计
1. 菜单权限
@ServicepublicclassMenuPermissionService{publicList<MenuVO>getUserMenus(LonguserId){// 获取用户角色List<Role>roles=roleMapper.selectByUserId(userId);// 获取角色对应的菜单Set<Long>menuIds=newHashSet<>();for(Rolerole:roles){List<Menu>menus=menuMapper.selectByRoleId(role.getId());menus.stream().map(Menu::getId).forEach(menuIds::add);}// 构建菜单树returnbuildMenuTree(menuIds);}}2. 数据权限
@ComponentpublicclassDataPermissionInterceptor{@AutowiredprivateDataScopeServicedataScopeService;@Around("@annotation(dataPermission)")publicObjectaround(ProceedingJoinPointpoint,DataPermissiondataPermission)throwsThrowable{// 获取用户数据权限范围DataScopescope=dataScopeService.getUserDataScope(getCurrentUserId());// 根据权限范围修改查询if(scope.getType()==DataScopeType.DEPT){// 只看本部门数据addDeptCondition(point,scope.getDeptIds());}elseif(scope.getType()==DataScopeType.SELF){// 只看自己创建的数据addSelfCondition(point,getCurrentUserId());}returnpoint.proceed();}}六、总结
权限系统设计要点:
- RBAC:简单易用,适合固定角色
- ABAC:灵活复杂,适合精细控制
- 菜单权限:控制可见性
- 数据权限:控制数据范围
个人观点,仅供参考