我在尝试使用 JavaConfig 而不是 XML 来实现 Spring Security 中的角色层次结构时遇到了一些问题。有没有办法使用 @Secured 注释而不是 HttpSecurity antMatchers 来实现角色层次结构?如果不提供正确的字符串模式,我似乎无法将角色层次结构添加到 HttpSecurity,尽管我希望能够专门使用 @Secured 做出访问决策。
java.lang.IllegalStateException: At least one mapping is required (i.e. authorizeRequests().anyRequest.authenticated())
@Bean
public RoleHierarchyImpl roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
return roleHierarchy;
}
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
return defaultWebSecurityExpressionHandler;
}
public void configure(HttpSecurity http){
http.authorizeRequests().expressionHandler(webExpressionHandler()).and().//other stuff
}
非常感谢对此的任何帮助。
最佳答案
我还想使用 @Secured 注释建立角色层次结构。发现它真的很棘手,但最终有了以下解决方案(常规代码)。
在@Configuration类中定义你的选民和决策管理者:
@Bean
public static RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl()
roleHierarchy.setHierarchy("""\
$SUPER_ADMIN > $ORGANIZATION_ADMIN
$ORGANIZATION_ADMIN > $DOCTOR
$DOCTOR > $NURSE
$NURSE > $PATIENT
$PATIENT > $USER""".stripIndent())
roleHierarchy
}
@Bean
public static RoleHierarchyVoter roleVoter() {
new RoleHierarchyVoter(roleHierarchy())
}
@Bean
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter> decisionVoters = new ArrayList<>();
decisionVoters.add(webExpressionVoter());
decisionVoters.add(roleVoter());
new AffirmativeBased(decisionVoters);
}
private WebExpressionVoter webExpressionVoter() {
WebExpressionVoter webExpressionVoter = new WebExpressionVoter()
webExpressionVoter.setExpressionHandler(expressionHandler())
webExpressionVoter
}
@Bean
public DefaultWebSecurityExpressionHandler expressionHandler(){
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy());
return expressionHandler;
}
然后在安全配置中添加决策管理器:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
...
.and()
.authorizeRequests()
.accessDecisionManager(accessDecisionManager())
.antMatchers("/auth").permitAll()
...
}
然后您还必须覆盖 GlobalMethodSecurityConfiguration 才能使用您的 RoleHierarchyVoter:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
new DefaultMethodSecurityExpressionHandler(roleHierarchy: SecurityConfiguration.roleHierarchy())
}
@Override
protected AccessDecisionManager accessDecisionManager() {
AffirmativeBased manager = super.accessDecisionManager() as AffirmativeBased
manager.decisionVoters.clear()
manager.decisionVoters << SecurityConfiguration.roleVoter()
manager
}
}
我正在删除其他投票者,只是在 AccessDecisionManager 中添加我的 RoleHierarchyVoter,但如果需要,您可以保留其他投票者。就我而言,我只使用 @Secured 注释,因此不需要其他注释。这是在任何地方都没有提到的部分,使其与 @Secured 注释一起使用。
<小时/>另一个解决方案是创建一个具有层次结构配置的 RoleHierarchy bean 并将其注入(inject)到您的自定义身份验证过滤器中,您可以在其中对用户进行身份验证并将权限传递给 UsernamePasswordAuthenticationToken 通过调用:
roleHierarchy.getReachableGrantedAuthorities(authorityFromUserDetails)
如果您不使用任何自定义授权,第二个解决方案会有点棘手,但就我而言,它更简单。
关于java - Spring Security 角色层次结构@Secured JavaConfig,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32970327/