Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 778
gipinani Avatar asked Feb 04 '14 13:02

gipinani


People also ask

How do I enable method level security in Spring?

Method-level security is implemented by placing the @PreAuthorize annotation on controller methods (actually one of a set of annotations available, but the most commonly used). This annotation contains a Spring Expression Language (SpEL) snippet that is assessed to determine if the request should be authenticated.

How do I enable global security?

The global method security functionality is disabled by default. To enable it, you use the @EnableGlobalMethodSecurity annotation over the configuration class of your application. You can apply authorization rules that the application checks before the call to a method.


1 Answers

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;
    }
}
like image 72
Rob Winch Avatar answered Sep 28 '22 05:09

Rob Winch