Spring: Enable global method security in Controller layer by java config

java, spring, spring-java-config, spring-mvc, spring-security

Solution

Update (after updated question)

It appears you are encountering SEC-2479. There are a few ways around this. The easiest of which is to use the result of @Autowired for the AuthenticationManager. To do this you must extend GlobalMethodSecurityConfiguration and override the authenticationManager method.

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    private AuthenticationManager am;

    @Override
    protected AuthenticationManager authenticationManager() {
        return am;
    }
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        // ... create and return custom MethodSecurityExpressionHandler ...
        return expressionHander;
    }
}

Original Answer

You need to configure some sort of Authentication. So you will need to have the following:

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

If you are not using web based security, the reference provides an example of how to configure the method security expression handler.

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        // ... create and return custom MethodSecurityExpressionHandler ...
        return expressionHander;
    }
}

If you are only wanting a custom method expression handler to provide a permission evaluator, then you only need to create a PermissionEvaluator bean like this:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
    @Bean
    public PermissionEvaluator permissionEvaluator() {
        // ... create and return custom PermissionEvaluator ...
        return permissionEvaluator;
    }
}

Problem

I'm trying to migrate my xml servlet config to java config. The below config is my servlet configuration, that enables custom security annotations on Controller layer. ``` <security:global-method-security pre-post-annotations="enabled"> <security:expression-handler ref="expressionHandler"/> </security:global-method-security> <bean id="expressionHandler" class="yyy.MyMethodSecurityExpressionHandler" /> ``` I've also have a working spring security xml configuration, that is in order to be replaced by java config, but not now. Here some pieces of my security config: ``` <bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDetailsService" /> </bean> <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> <constructor-arg> <ref bean="authenticationProvider"/> </constructor-arg> </bean> <security:authentication-manager> <security:authentication-provider user-service-ref="userDetailsService" /> </security:authentication-manager> <security:global-method-security pre-post-annotations="enabled" /> ``` I want to start to migrate my servlet config enabling security `@PreAuthorize` and `@PostAuthorize` tag in Controller layer. I've found this annotation: `@EnableGlobalMethodSecurity(prePostEnabled=true)`, but putting it on my servlet config: ``` @Configuration @ComponentScan(basePackages= { "....." }) @EnableGlobalMethodSecurity(prePostEnabled=true) public class WebappServletConfig extends WebMvcConfigurationSupport { ``` I get this exception: ``` java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found [] ``` Moreover I don't know how to set my custom expression-handler! someone with some tips? Thank you

Original source