RuoYi系统角色权限划分与控制
RuoYi 采用RBAC基于角色的访问控制模型核心关系用户 → 角色 → 菜单/权限按钮。权限字符串格式为系统:模块:操作如system:user:add。下面分权限划分、页面权限、按钮权限、后端接口权限四部分说明并附完整可运行代码示例。一、角色与权限划分核心模型1. 数据库表关系核心sys_user用户sys_role角色sys_menu菜单/按钮含权限字段permssys_user_role用户 ↔ 角色关联sys_role_menu角色 ↔ 菜单/按钮关联2. 权限级别菜单权限控制左侧菜单是否显示页面级按钮权限控制页面内按钮/元素显示元素级接口权限后端接口访问控制API 级数据权限控制数据范围部门/本人等3. 权限标识规范系统:模块:操作 system:user:list # 用户列表 system:user:add # 新增 system:user:edit # 编辑 system:user:remove # 删除 system:user:export # 导出 *:*:* # 超级管理员所有权限二、页面路由权限控制1. 前端路由守卫Vue 版src/permission.js路由拦截importrouterfrom./routerimport{ElMessage}fromelement-plusimportuseUserStorefrom/store/modules/user// 白名单constwhiteList[/login,/register]router.beforeEach((to,from,next){constuserStoreuseUserStore()// 已登录if(userStore.token){if(to.path/login){next({path:/})}else{// 判断是否有用户信息if(userStore.permissions.length0){// 获取用户信息、权限userStore.getInfo().then((){next({...to,replace:true})}).catch(err{userStore.logout().then((){ElMessage.error(err||权限校验失败)next(/login)})})}else{next()}}}else{// 未登录if(whiteList.includes(to.path)){next()}else{next(/login)}}})2. 动态路由后端返回菜单src/store/modules/user.js获取权限import{login,logout,getInfo}from/api/loginimport{defineStore}frompiniaconstuseUserStoredefineStore(user,{state:()({token:localStorage.getItem(token)||,permissions:[],// 权限标识集合roles:[]// 角色集合}),actions:{// 获取用户信息getInfo(){returnnewPromise((resolve,reject){getInfo().then(res{constuserres.user// 超级管理员if(user.userId1){this.permissions[*:*:*]}else{this.permissionsres.permissions}this.rolesres.rolesresolve(res)}).catch(errreject(err))})}}})三、按钮元素权限控制最常用1. 自定义指令v-hasPermi核心1指令定义src/directive/permission/hasPermi.jsimportuseUserStorefrom/store/modules/userexportdefault{mounted(el,binding){const{value}bindingconstall_permission*:*:*constuserStoreuseUserStore()constpermissionsuserStore.permissionsif(valueArray.isArray(value)value.length0){// 判断是否有权限consthasPermissionpermissions.some(perm{returnall_permissionperm||value.includes(perm)})// 无权限则移除元素if(!hasPermission){el.parentNodeel.parentNode.removeChild(el)}}else{thrownewError(请设置权限标识如 v-hasPermi[system:user:add])}}}2指令注册src/directive/index.jsimporthasPermifrom./hasPermiimporthasRolefrom./hasRoleexportdefaultfunctiondirective(app){app.directive(hasPermi,hasPermi)// 权限指令app.directive(hasRole,hasRole)// 角色指令}3全局注册src/main.jsimport{createApp}fromvueimportAppfrom./App.vueimportdirectivefrom./directiveconstappcreateApp(App)directive(app)// 注册所有指令app.mount(#app)2. 页面按钮使用示例Vue 模板template div !-- 单个权限新增按钮 -- el-button typeprimary iconplus v-hasPermi[system:user:add] clickhandleAdd 新增用户 /el-button !-- 单个权限编辑按钮 -- el-button typesuccess iconedit v-hasPermi[system:user:edit] clickhandleEdit 编辑 /el-button !-- 多个权限满足其一 -- el-button typewarning v-hasPermi[system:user:export, system:user:view] 导出/查看 /el-button !-- 角色控制仅 admin 可见 -- el-button typedanger v-hasRole[admin] clickhandleDelete 删除 /el-button /div /template3. 表格操作列示例el-table-column label操作 width180 template #defaultscope el-button sizemini text iconedit v-hasPermi[system:user:edit] clickhandleEdit(scope.row) 编辑 /el-button el-button sizemini text icondelete v-hasPermi[system:user:remove] clickhandleDelete(scope.row) 删除 /el-button /template /el-table-column四、后端接口权限控制Spring Boot 版1. 注解方式PreAuthorize/RequiresPermissions1Controller 层页面/按钮对应接口RestControllerRequestMapping(/system/user)publicclassSysUserController{/** * 查询用户列表页面权限 */PreAuthorize(hasPermission(system:user:list))GetMapping(/list)publicTableDataInfolist(SysUseruser){startPage();ListSysUserlistuserService.selectUserList(user);returngetDataTable(list);}/** * 新增用户按钮权限 */PreAuthorize(hasPermission(system:user:add))PostMappingpublicAjaxResultadd(RequestBodySysUseruser){returntoAjax(userService.insertUser(user));}/** * 修改用户按钮权限 */PreAuthorize(hasPermission(system:user:edit))PutMappingpublicAjaxResultedit(RequestBodySysUseruser){returntoAjax(userService.updateUser(user));}/** * 删除用户按钮权限 */PreAuthorize(hasPermission(system:user:remove))DeleteMapping(/{userIds})publicAjaxResultremove(PathVariableLong[]userIds){returntoAjax(userService.deleteUserByIds(userIds));}}2权限实现UserRealmShiro 版publicclassUserRealmextendsAuthorizingRealm{OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){SysUseruserShiroUtils.getSysUser();SimpleAuthorizationInfoinfonewSimpleAuthorizationInfo();// 超级管理员if(user.isAdmin()){info.addStringPermission(*:*:*);}else{// 获取用户权限SetStringpermsmenuService.selectPermsByUserId(user.getUserId());info.setStringPermissions(perms);}returninfo;}}五、权限配置后台操作菜单管理新增菜单/按钮填写权限字符如system:user:add角色管理给角色分配菜单/按钮权限用户管理给用户分配角色六、总结页面权限路由守卫 动态菜单按钮权限v-hasPermi自定义指令前端隐藏接口权限PreAuthorize后端拦截权限字符串系统:模块:操作统一易维护