角色继承与权限完善
角色继承
有时候角色与用户并不是完全一一对应的,在刚开始的时候,admin
用户可能只有ROLE_ADMIN
角色,manager
用户也只有ROLE_MANAGER
角色。
但如果希望给admin
用户授予manager
的角色,该怎么办呢?
这就需要用到Spring Security的角色继承
功能了。
在用户表中增加employee
用户。
INSERT INTO sys_user VALUES (3, 'employee', '123456', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
给employee
用户赋予ROLE_EMPLOYEE角色。
INSERT INTO sys_role VALUES (3, 'ROLE_EMPLOYEE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
然后配置角色权限。
INSERT INTO sys_permission VALUES (5,3,'/employee','read',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
INSERT INTO sys_permission VALUES (6,3,'/employee','remove',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
修改LoginController
登录类。
......
@GetMapping("/employee")
@PreAuthorize("hasRole('ROLE_EMPLOYEE')")
public String employee() {
return "employee有ROLE_EMPLOYEE角色";
}
......
然后修改WebSecurityConfiguration
,引入RoleHierarchy
角色继承类。
......
// 角色继承
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
// 多个角色用【>】表示,【>】左边角色的权限要大于右边角色的权限
String hierarchy = "ROLE_ADMIN > ROLE_MANAGER " + System.lineSeparator() + " ROLE_MANAGER > ROLE_EMPLOYEE";
// 也可以写成 "ROLE_ADMIN > ROLE_MANAGER > ROLE_EMPLOYEE";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
......
运行Postman,测试用户各自的所拥有的角色是否能访问成功。
admin
:拥有{ ROLE_ADMIN, ROLE_MANAGER, ROLE_EMPLOYEE }
。manager
:拥有{ ROLE_MANAGER, ROLE_EMPLOYEE }
。employee
:拥有{ ROLE_EMPLOYEE }
。
结合之前的权限细化,可以看到Spring Security有以下几个特点。
角色可以被继承,但权限并不能
跟随
角色一起被继承。admin
只能访问/admin/create
和/admin/read
这两个接口。manager
只能访问/manager/create
和/manager/remove
这两个接口。admin
虽然继承了角色ROLE_MANAGER
,但并没有获得ROLE_MANAGER
对应的权限。
这说明加入权限后,Spring Security的角色继承就会失效。
权限完善
因为权限无法跟随角色被继承,所以需要手动去完善它。
为了让admin
也能访问manager
的接口,就要赋予角色更多的权限。
现在把manager
和employee
的权限都赋予admin
。
在权限表中增加如下记录。
INSERT INTO sys_permission VALUES (7,1,'/manager','create', CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
INSERT INTO sys_permission VALUES (8,1,'/manager','remove', CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
INSERT INTO sys_permission VALUES (9,1,'/employee','read', CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
INSERT INTO sys_permission VALUES (10,1,'/employee','remove', CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
在LoginController
登录类中给employee
增加权限。
......
@GetMapping("/employee/read")
@PreAuthorize("hasPermission('/employee', 'read')")
public String employeeRead() {
return "employee有ROLE_EMPLOYEE角色的read权限";
}
@GetMapping("/employee/remove")
@PreAuthorize("hasPermission('/employee', 'remove')")
public String employeeRemove() {
return "employee有ROLE_EMPLOYEE角色的remove权限";
}
再用Postman访问接口,通过admin
用户登录,分别做以下测试。
接口 | 访问结果 |
---|---|
/admin/create | 成功 |
/admin/read | 成功 |
/manager/create | 成功 |
/manager/remove | 成功 |
/employee/read | 成功 |
/employee/remove | 成功 |
可以看到,admin
已经具备了manager
和employee
权限。
Spring Security比较简单,也很方便,多适用于一些比较小型的应用系统,角色简单,权限不多。
如果要实现一些比较复杂的权限功能,Spring Security就会有点力不从心了,而且会出现诸如自定义filter
被执行多次的问题。
所以,一般在大型或企业级应用中,不会完全依赖Spring Security,而是依据实际业务需求,实现自定义的RBAC权限系统。
感谢支持
更多内容,请移步《超级个体》。