天天看點

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

[email protected]使用方法

在對應的方法上使用注解

@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接口

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

源碼中攔截了5個注解,其中包括@RequiresPermissions

在這個切點中,調用了performBeforeInterception方法

繼續追蹤源碼發

調用AnnotationsAuthorizingMethodInterceptor(類名中文意思:注解授權方法攔截者 )中的

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

繼續往下

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

 5個注解對應5種不同的handler

這裡我們隻看PermissionAnnotationHandler

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

看名稱就知道終于到了最重要的實作代碼

checkPermission(檢查權限)

在這裡擷取到注解中value的權限,與目前使用者的權限做對比即可

具體檢查的源碼就不具體看了,可以想象成字元串比較,當然源碼中不會這麼簡單

下圖為關鍵部分源碼,對注釋做了翻譯

AnnAnnotationsAAnnotationsAuthorizingM

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

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方法中被調用

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

代碼中紅框部分:Shrio會根據使用者配置的緩存方式将權限集合存儲在緩存中

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

而在checkPermission 中通過緩存擷取該權限集合進行對比檢查

apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析
apache shiro架構@RequiresPermissions源碼分析[email protected]使用方法2.分析實作過程3.源碼分析

這裡的session是shrio中session,并不是web容器中的。

最終将注解中value的權限與session中緩存的目前使用者權限進行checkpermission,判斷使用者是否有權限通路。

AnnotationsAuthorizingAnnotationsAuthorizingMethodInterceptorMethodInterceptor

繼續閱讀