前言:RuoYi框架中,菜单管理的权限标识字段通常用于定义用户对特定菜单或操作的访问权限。
这个权限标识字段通常会被用在两个地方:
1. 后端:在Spring Security的@PreAuthorize注解中,用于控制对特定方法的访问。例如,@PreAuthorize("hasAuthority('monitor:job:add')")会在执行方法前检查用户是否具有monitor:job:add这个权限。
2. 前端:在Vue.js的v-hasPermi指令中,用于控制基于权限的UI元素的显示和隐藏。例如,v-hasPermi="['monitor:job:add']"会检查用户是否具有monitor:job:add这个权限,如果有,那么相关的UI元素就会显示。
通过这种方式,RuoYi框架可以实现精细的基于权限的访问控制,确保只有具有相应权限的用户才能访问特定的资源。
详细整理如下:
当用户登录系统的时候,会调用getInfo接口,在该接口中会将用户、权限、角色等集合信息返回给前端。
获取用户信息:
从request请求中,获取token进而获取用户信息
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
获取角色集合:
根据userId获取当前用户角色集合
Set<String> roles = roleService.selectRolePermissionByUserId(user.getUserId());
核心的sql语句 匹配出当前用户拥有哪些角色
select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope,
r.status, r.del_flag, r.create_time, r.remark
from sys_role r
left join sys_user_role ur on ur.role_id = r.role_id
left join sys_user u on u.user_id = ur.user_id
left join sys_dept d on u.dept_id = d.dept_id
WHERE r.del_flag = '0' and ur.user_id = #{userId}
获取权限集合:
通过user对象获取当前用户的权限集合
Set<String> permissions = permissionService.getMenuPermission(user);
核心sql语句 通过userId获取当前用户所有角色的所有权限
select distinct m.perms
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
left join sys_role r on r.role_id = ur.role_id
where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
@PreAuthorize注解工作流程
用户此时已经登陆系统,假设用户操作的是角色管理模块的查询按钮,当点击该按钮时,会通过网络映射到后端的接口方法。
当这个请求到达被@PreAuthorize注解的方法时,Spring Security的拦截器会拦截这个请求。
拦截器会获取到@PreAuthorize注解中的表达式,并使用Spring EL表达式语言对其进行求值。这个过程通常会涉及到当前用户的认证信息,例如用户的角色、权限等。根据表达式的求值结果,Spring Security会做出访问控制决策。如果表达式求值为true,那么请求会被允许继续执行;如果表达式求值为false,那么请求会被拒绝,通常会返回一个HTTP 403 Forbidden错误。
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role)
{
startPage();
List<SysRole> list = roleService.selectRoleList(role);
return getDataTable(list);
}
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission)
{
if (StringUtils.isEmpty(permission))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
return hasPermissions(loginUser.getPermissions(), permission);
}
如果当前用户的权限集合中,包含当前被@PreAuthorize标注的方法的权限,则返回true。
/**
* 判断是否包含权限
*
* @param permissions 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean hasPermissions(Set<String> permissions, String permission)
{
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
如果请求被允许继续执行,那么被@PreAuthorize注解的方法会被调用。