AccessDecisionVoter Deprecated with Spring Security 6.x
Asked Answered
H

2

6

In Spring Boot 2.7.x , I used the RoleHierarchyVoter

public RoleHierarchy roleHierarchy() {
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    roleHierarchy.setHierarchy("ROLE_ADMINISTRATOR > ROLE_USER > ROLE_GUEST");
    return roleHierarchy;
}

@Bean
public RoleHierarchyVoter roleVoter() {
    return new RoleHierarchyVoter(roleHierarchy());
}

In Spring Boot 3.x AccessDecisionVoter are deprecated - the use of AuthorizationManager is recommended. Is there any posibility to use an AuthorizationManager-Implementation to set a role hierarchy? The usage of

@Bean
AccessDecisionVoter hierarchyVoter() {
    RoleHierarchy hierarchy = new RoleHierarchyImpl();
    hierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF > ROLE_USER" +
            "ROLE_USER > ROLE_GUEST");
    return new RoleHierarchyVoter(hierarchy);
}

did not work since I use the AuthorizationFilter.

Holograph answered 11/12, 2022 at 18:4 Comment(1)
This might help you docs.spring.io/spring-security/reference/5.8/migration/servlet/…Mcgurn
V
2

Simply exposing a expressionHandler bean should do the job.

If you use method security (@EnableMethodSecurity) :

@Bean
public RoleHierarchyImpl roleHierarchy() {
    final RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF > ROLE_USER > ROLE_GUEST");
    return roleHierarchy;
}

@Bean
public DefaultMethodSecurityExpressionHandler expressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
    expressionHandler.setRoleHierarchy(roleHierarchy());
    return expressionHandler;
}

If you use web security (@EnableWebSecurity) :

@Bean
public RoleHierarchyImpl roleHierarchy() {
    final RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF > ROLE_USER > ROLE_GUEST");
    return roleHierarchy;
}

@Bean
public DefaultWebSecurityExpressionHandler expressionHandler() {
    DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
    expressionHandler.setRoleHierarchy(roleHierarchy());
    return expressionHandler;
}

EDIT

setHierarchy is deprecated since 7.0, you can now directly use :

return RoleHierarchyImpl.fromHierarchy("ROLE_ADMIN > ROLE_STAFF > ROLE_USER > ROLE_GUEST");
Vitavitaceous answered 11/12, 2022 at 21:49 Comment(4)
This does not work. I filed an issue in spring security team github.com/spring-projects/spring-security/issues/12473Untried
I implemented this solution which is working in spring security 6.0.0 and spring boot 3.0.0 https://mcmap.net/q/1916060/-roles-hierarchy-not-working-after-upgrading-to-spring-security-6Untried
Thanks for the feedback. Actually this is what I use with Spring Boot 3 and Spring Security 6 and it works totally fine, at least for method security (@PreAuthorize).Vitavitaceous
It works fine (Spring Boot 3.0.2) but I had to annotate the class also with @Configuration; which it was not necessary in Spring Boot 2.7.xSpotter
H
0

First, you create and instance of AuthorizationManager:

var access = AuthorityAuthorizationManager.<RequestAuthorizationContext>hasRole("USER");

This instance will be used to authorize our endpoints. So in the hasRole method, provide the name of your role or roles you want to use to protect a specific endpoint.

Second, you define your role hierarchy:

var hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");

In this case we are defining that ROLE_ADMIN is above ROLE_USER, so ROLE_ADMIN has the same role as an ROLE_USER.

Third, we set the RoleHierarcy instance in the AuthorizationManager instance:

access.setRoleHierarchy(hierarchy);

Finally, we set the AuthorizationManager instance in our route protection configuration. So all the code togheter would look like this:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        var access = AuthorityAuthorizationManager.<RequestAuthorizationContext>hasRole("USER");
        var hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        access.setRoleHierarchy(hierarchy);

        http.authorizeHttpRequests(authorize -> authorize.anyRequest().access(access));

        return http.build();

    }
Holotype answered 9/2, 2023 at 1:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.