Reputation: 14408
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
Upvotes: 6
Views: 24293
Reputation: 21720
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;
}
}
Upvotes: 5
Reputation: 5004
first of all you need a separate Configuration class like
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {...
where you need to define
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
that should help with your exception.
I am not sure how to configure expressionHandler, but seems you can tweak it in configure(WebSecurity web)
@Override
public void configure(WebSecurity web) throws Exception {
web.expressionHandler().....
}
Upvotes: 3