[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接口
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPBpWTxMWbixmWtJGbkhlWwh2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1ETO2MTOwETMyIDNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
源碼中攔截了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