Spring Security 实现角色继承
本文描述如何基于Spring Security 实现角色继承。
权限声明
很多应用基于Spring Security 实现认证过程,通常需要定义一些角色,这些角色可能会有优先级或层次关系。假设我们有三个角色:
ADMIN, MODERATOR ,USER.
下面代码进行权限声明:
@Secured(['MODERATOR'])
def dashBoard(){
render(view: 'dashBoard')
}
我们看到通过注解限制角色访问。如果你想ADMIN用户也要访问,我们需要增加角色声明:
@Secured(['ADMIN','MODERATOR'])
这样能够实现需求,但在我们系统中有很多这样场景,因此采用这种方式显得很啰嗦。
实现角色继承
为了实现角色继承,需要下面两步:
- 定义bean RoleHierarchy
- 定义 expressionhandler 读角色继承关系
示例配置代码:
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
@EnableWebSecurity
public class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter{
private SecurityExpressionHandler<filterinvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
return defaultWebSecurityExpressionHandler;
}
@Bean
public RoleHierarchy roleHierarchy(){
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ADMIN > MODERATOR > USER");
return roleHierarchy;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("ekansh")
.password("password")
.authorities("USER", "ROLE");
auth.inMemoryAuthentication()
.withUser("admin")
.password("admin")
.authorities("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.expressionHandler(webExpressionHandler())
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAuthority("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
;
}
}
上面示例,角色继承关系如下:
- ADMIN 能访问 MODERATOR 和 USER 角色权限.
- MODERATOR 能访问 USER 角色权限.
- USER 及不能访问 MODERATOR 角色,也不能访问 ADMIN 角色权限.
总结
通过角色继承使得配置和管理角色和角色权限更简单。