之前我们再shiro中已经实现了认证数据的数据库获取,权限数据的数据库获取,最后我们再来看一下有关权限字符串集合的获取,其实权限字符串的获取和角色的获取集合也是大同小异的,下面就可以来看一下这个权限的细粒度的权限控制。
首先我们来分析一下,在数据库中的表:分别是 t_role,t_perms,t_role_perms这三张表,t_role是角色表,t_perms为权限表,t_roler_perms为权限与角色的中间表,那么我们最终的目的就是要通过角色id来获取权限字符串,url,角色名称。
那么想好需要什么,那几张表,这样我们就可以写sql了:
SELECT p.id,p.perms_name name,p.url,r.rolename
FROM t_role r
LEFT JOIN t_role_perms rp
ON r.id = rp.role_id
LEFT JOIN t_perms p
ON rp.perms_id = p.id
WHERE r.id = '#{id}'
这个sql的含义就是通过id来获取权限信息和角色信息以及url,我们再将roleid标为1,查询的结果
编写dao层方法:
/**
* 根据角色Id查询权限信息
* @param Id
* @return
*/
List<Perms> findPermsByRoleId(@Param("Id")String Id);
service层方法:
/**
* 根据角色Id查询权限信息
* @param Id
* @return
*/
List<Perms> findPermsByRoleId(String Id);
业务层实现类:
/**
* 根据角色Id查询权限信息
* @param Id 角色Id
* @return
*/
@Override
public List<Perms> findPermsByRoleId(String Id) {
return userDao.findPermsByRoleId(Id);
}
上面通过角色id获取权限字符串的方法完成了之后,我们接下来就需要去自定义Realm去看一下了,在自定义Realm中我们还需要将权限字符串信息放入到simpleAuthorizationInfo中:
public class MyRealm extends AuthorizingRealm {
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//首先拿到用户的主身份信息
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
//用获取容器中对象的工具类拿到userService对象
UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
//授权角色信息、角色集合
User user = userService.findRolesByUsername(primaryPrincipal);
//使用CollectionUtils方法判空,如果roles集合非空说明有角色信息
if (!CollectionUtils.isEmpty(user.getRoles())){
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//遍历角色集合之后添加角色字符串
user.getRoles().forEach(role -> {
//遍历出每个角色对象,拿到名称
simpleAuthorizationInfo.addRole(role.getName());
//调用业务层方法,通过角色id拿到权限字符串信息
List<Perms> perms = userService.findPermsByRoleId(role.getId());
//判断权限字符串集合不为空
if (!CollectionUtils.isEmpty(perms)){
//遍历权限字符串集合
perms.forEach(perm -> {
//拿到每个权限字符对象获取名字属性
simpleAuthorizationInfo.addStringPermission(perm.getName());
});
}
});
//返回授权信息
return simpleAuthorizationInfo;
}
return null;
}
在上面的自定义Realm中我们可以看到我们再遍历角色集合的时候,拿到角色对象之后获取角色名称,然后添加角色,同样的,我们在这个方法中调用业务层的对象,通过角色的id获取到了权限字符串的集合,然后遍历这个权限字符串集合之后拿到权限字符串名称,并添加,最终返回权限信息。
这样的话我们可以看一下目前我们的数据库信息,admin是拥有user用户模块的全部权限的,所以在之前我们的admin包括zhangsan用户登录进来是看不到用户模块的下属菜单的,那现在我们可以登录看一下效果:
可以看到,现在我们不论是zhangsan还是admin用户都能展示出来我们的用户管理这个模块的下属菜单。
为了看效果,我们再给admin加一个order:*:*的权限,并且将前端页面的用户修改改为有order权限才能展示,之后再用zhangsan登录看一下效果:
此时用户修改只有拥有order权限才能展示,此时admin用户拥有order:*:*权限,zhangsan没有,首先是admin登录:
可以看到admin还是可以看到所有的菜单,而zhangsan呢?
可以看到,张三并没有用户修改的权限,这就是细粒度的权限控制,权限字符串的简单实现。