1.@RequiresPermissions使用方法
在对应的方法上使用注解
@RequestMapping("user/list")
@RequiresPermissions("user:list")
@ResponseBody
public Map<String, Object> userList(QueryRequest request, User user) {
return super.selectByPageNumSize(request, () -> this.userService.findUserWithDept(user, request));
}
功能说明:如果当前登录用户包含该权限(user的list查询权限),用户才能访问这个接口获取数据
2.分析实现过程
1.在用户调用接口userList,通过@RequiresPermissions对方法进行拦截
2.获取到@RequiresPermissions注解中的value字符串“user:list”与数据库中配置的该用户的权限做对比
分析:框架做的事情就是把这些过程封装好,我们要做的很简单,设置user权限集合,在方法上对应的注解中添加权限即可。
3.源码分析
1.shiro源码AOP切面类
用来拦截userList接口
源码中拦截了5个注解,其中包括@RequiresPermissions
在这个切点中,调用了performBeforeInterception方法
继续追踪源码发
调用AnnotationsAuthorizingMethodInterceptor(类名中文意思:注解授权方法拦截者)中的
继续往下
5个注解对应5种不同的handler
这里我们只看PermissionAnnotationHandler
看名称就知道终于到了最重要的实现代码
checkPermission(检查权限)
在这里获取到注解中value的权限,与当前用户的权限做对比即可
具体检查的源码就不具体看了,可以想象成字符串比较,当然源码中不会这么简单
下图为关键部分源码,对注释做了翻译
AnnAnnotationsAAnnotationsAuthorizingM
2.下一个问题,如何获取到当前用户的权限?
权限设置(这段不是源码,是我们使用shiro框架需要写的部分)
在代码中我们需要继承AuthorizingRealm类,重写doGetAuthorizationInfo方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
String userName = user.getUsername();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 获取用户角色集
List<Role> roleList = this.roleService.findUserRole(userName);
Set<String> roleSet = roleList.stream().map(Role::getRoleName).collect(Collectors.toSet());
simpleAuthorizationInfo.setRoles(roleSet);
// 获取用户权限集
List<Menu> permissionList = this.menuService.findUserPermissions(userName);
Set<String> permissionSet = permissionList.stream().map(Menu::getPerms).collect(Collectors.toSet());
simpleAuthorizationInfo.setStringPermissions(permissionSet);
return simpleAuthorizationInfo;
}
重写的方法会在AuthorizingRealm类的getAuthorizationInfo方法中被调用
代码中红框部分:Shrio会根据用户配置的缓存方式将权限集合存储在缓存中
而在checkPermission 中通过缓存获取该权限集合进行对比检查
这里的session是shrio中session,并不是web容器中的。
最终将注解中value的权限与session中缓存的当前用户权限进行checkpermission,判断用户是否有权限访问。
AnnotationsAuthorizingAnnotationsAuthorizingMethodInterceptorMethodInterceptor