此处不再说明springboot集成shiro相关内容,如有不懂集成的可以搜素相关帖子。
场景:多项目管理中,各个项目分配给同一个账号不同权限,在进行项目切换中权限会统一查询导致权限范围蔓延扩大,需要进行项目级的权限隔离;
1、首先在ShiroConfig中设置ShiroRealm的名称(可以省略,但是建议设置),此处设置后再后续清除缓存时需要用到;
@Bean
public ShiroRealm shiroRealm() {
ShiroRealm shiroRealm = new ShiroRealm();
//此处设置缓存信息在缓存中的名称
shiroRealm.setName("mpm");
shiroRealm.setCacheManager(cacheManager());
return shiroRealm;
}
2、在ShiroRealm中对doGetAuthorizationInfo 方法进行改造,需要在查询权限时根据当前的项目进行查询;当然此方法在项目中只触发一次(未清除shiro缓存情况下)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
UserModel loginModel = (UserModel) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if (loginModel.getIsAdmin() != null && loginModel.getIsAdmin()) {
info.addStringPermission("*:*");
return info;
}
//此处需要提前缓存切换的项目id,否则获取不到当前项目
//根据项目id查询用户在项目下的角色所属的资源信息
Long projectId = Long.valueOf((String.valueOf(SecurityUtils.getSubject().getSession().getAttribute("projectId"))));
List<String> permissionList = new ArrayList<>();
if (projectId == null) {
permissionList = this.resourceService.selectResourceByUserId(loginModel.getId());
} else {
permissionList = this.resourceService.selectResourceByUserIdAndProjectId(loginModel.getId(), projectId);
}
info.addStringPermissions(permissionList);
return info;
}
3、在前端页面进行项目切换时,请求后台过程中进行权限缓存清除。shiro在进行权限校验时优先查询缓存信息,如没有缓存信息会触发doGetAuthorizationInfo 方法进行初始化后存入缓存中;
在需要清除缓存的类中注入shiro集成的缓存服务,如当前项目集成的是CacheManager;在切换方法中执行清除缓存,如此可以实现动态权限;
//缓存名称的前缀mpm在ShiroConfig中设置 后缀.authorizationCache为shiro默认的后缀名称
//这个方法的用途是清除当前用户的授权缓存信息 SecurityUtils.getSubject().getPrincipals()获取的是当前用户信息对象
cacheManager.getCache("mpm.authorizationCache").remove(SecurityUtils.getSubject().getPrincipals());
如此,大功告成;