在本节中,补充下角色继承的知识点。角色继承其实是一个十分常见的需求,因为一般系统中角色权限呈金字塔型,高层用户拥有底层用户的权限。
例如存在以下角色:普通用户、VIP 用户、SVIP 用户、星悦会员,那么对应的权限可以是“星悦会员 > SVIP 用户 > VIP 用户 > 普通用户”。那么如何在 Spring Security 中实现这样的功能呢?
引言
为了简便起见,我直接使用《SpringBoot 集成 Spring Security(1)——入门程序》 的代码。
在该章中,我们存在两个角色,ROLE_ADMIN
和 ROLE_USER
,并且经过我们的实验,/admin
接口只有 ROLE_ADMIN 有权限,/user
接口只有 ROLE_USER 有权限。
但是如果我想让 ROLE_ADMIN 用户继承 ROLE_USER 用户的所有权限,该如何做呢?
RoleHierarchy
这里就需要引入 RoleHierarch
了,我们只需要自定义一个 RoleHierarchy,并将其注入容器即可。修改 WebSecurityConfig
,在其中注入 RoleHierarchy:
@Bean
public RoleHierarchy roleHierarchy(){
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ROLE_ADMIN > ROLE_USER";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
roleHierarchy.setHierarchy()
指定了角色的继承关系,参数就是一个字符串,比大小即可,是不是非常简单?
让我们使用 ROLE_ADMIN 账号登陆,发现原本无法访问的 /user
接口也可以访问了:
源码
角色关系的实现也比较简单,本质就是将字符串使用正则切分,并将角色关系存放进一个 Map 中,map 的 key 是大的角色,value 是一个 Set,存放所有比它小的角色。然后交由后续处理,有兴趣的可以继续阅读源码。
如果有多个继承关系,在 SpringBoot 2.1 中,就应该改写为:
@Bean
public RoleHierarchy roleHierarchy() {
String separator = System.lineSeparator();
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ROLE_ADMIN > ROLE_USER " + separator + " ROLE_USER > ROLE_TOURISTS";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
另外换行符大家都知道在不同系统中表示不一样,例如 Windows 中为 \r\n
,Mac 为 \r
,Linux 为 \n
,因此以上代码我是用的 java.lang
包的 System 类中封装的方法,不用判断当前操作系统。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!