ChetakS
ChetakS

Reputation: 31

Using custom AccessDecisionManager with HttpSecurity addFilterBefore does not work

The custom AccessDecisionManager does not get invoked either when filter is added or otherwise. Ideally would like to set filterBefore and custom AccessDecisionManager (using SpringBoot 1.5.2-release version). Alternately would like to call setRolePrefix on default RoleVoter. Also added DefaultRolesPrefixPostProcessor as mentioned in Section 8.3 of Spring 3 to 4 migration guide, but still RoleVoter looks for "ROLE_" prefix

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    AuthenticationFilter authenticationFilter;

    @Bean
    public AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters 
          = Arrays.asList(
            new WebExpressionVoter(),
            new RoleVoter(),
            new AuthenticatedVoter());
        return new AffirmativeBased(decisionVoters);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests().accessDecisionManager(accessDecisionManager())
        .anyRequest().authenticated(); 

        http.addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class);
    }
}

Upvotes: 3

Views: 1791

Answers (1)

NatFar
NatFar

Reputation: 2220

It seems like you're expecting your AccessDecisionManager to get called to grant/deny access to your secure methods.

Try the following:

  1. Remove the @EnableGlobalMethodSecurity annotation from your SecurityConfig.

  2. Move the annotation to another configuration class that extends GlobalMethodSecurityConfiguration.

For example:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    AccessDecisionManager accessDecisionManager;

    @Override
    protected AccessDecisionManager accessDecisionManager() {
        return this.accessDecisionManager;
    }

}

Explanation:

GlobalMethodSecurityConfiguration takes care of creating the method interceptors, and it doesn't look for an AccessDecisionManager bean to use. It must be provided one via an overridden method.

NOTE: By default, two AccessDecisionManagers are used: one for filters (created by AbstractInterceptUrlConfigurer) and another to secure methods (created by GlobalMethodSecurityConfiguration).

Alternately would like to call setRolePrefix on default RoleVoter

You could do this without ever touching the default AccessDecisionManagers:

@Bean
public GrantedAuthorityDefaults grantedAuthorityDefaults() {
    return new GrantedAuthorityDefaults("");
}

This will set the role prefix to "" on both default AccessDecisionManagers.

Upvotes: 3

Related Questions