Peter Andres
Peter Andres

Reputation: 61

AccessDecisionVoter Deprecated with Spring Security 6.x

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.

Upvotes: 6

Views: 5238

Answers (2)

Yann39
Yann39

Reputation: 15729

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");

Upvotes: 2

Artenes Nogueira
Artenes Nogueira

Reputation: 1552

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();

    }

Upvotes: 0

Related Questions