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