apache shiro框架@RequiresPermissions源碼分析

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章