【架构实战】权限系统设计:RBAC vs ABAC

张开发
2026/4/11 17:39:17 15 分钟阅读

分享文章

【架构实战】权限系统设计:RBAC vs ABAC
一、权限模型概述权限系统是应用安全的基础权限模型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{// 获取用户权限publicSetStringgetUserPermissions(LonguserId){ListPermissionpermissionspermissionMapper.selectByUserId(userId);returnpermissions.stream().map(Permission::getPermCode).collect(Collectors.toSet());}// 检查权限publicbooleanhasPermission(LonguserId,Stringpermission){SetStringpermissionsgetUserPermissions(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){// 加载匹配的策略ListPolicypoliciespolicyRepository.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){Conditionconditionrule.getCondition();returnevaluateCondition(condition,subject,resource,action);}}四、RBAC vs ABAC对比维度RBACABAC复杂度低高灵活性低高维护成本低高粒度角色级属性级适用场景固定角色复杂权限五、权限系统设计1. 菜单权限ServicepublicclassMenuPermissionService{publicListMenuVOgetUserMenus(LonguserId){// 获取用户角色ListRolerolesroleMapper.selectByUserId(userId);// 获取角色对应的菜单SetLongmenuIdsnewHashSet();for(Rolerole:roles){ListMenumenusmenuMapper.selectByRoleId(role.getId());menus.stream().map(Menu::getId).forEach(menuIds::add);}// 构建菜单树returnbuildMenuTree(menuIds);}}2. 数据权限ComponentpublicclassDataPermissionInterceptor{AutowiredprivateDataScopeServicedataScopeService;Around(annotation(dataPermission))publicObjectaround(ProceedingJoinPointpoint,DataPermissiondataPermission)throwsThrowable{// 获取用户数据权限范围DataScopescopedataScopeService.getUserDataScope(getCurrentUserId());// 根据权限范围修改查询if(scope.getType()DataScopeType.DEPT){// 只看本部门数据addDeptCondition(point,scope.getDeptIds());}elseif(scope.getType()DataScopeType.SELF){// 只看自己创建的数据addSelfCondition(point,getCurrentUserId());}returnpoint.proceed();}}六、总结权限系统设计要点RBAC简单易用适合固定角色ABAC灵活复杂适合精细控制菜单权限控制可见性数据权限控制数据范围个人观点仅供参考

更多文章