I'm trying to define access rules at method-level but it's not working what so ever.
SecurityConfiguration
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
withUser("user").password("user").roles("USER").and().
withUser("admin").password("admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v2/**").authenticated()
.and()
.httpBasic()
.realmName("Secure api")
.and()
.csrf()
.disable();
}
}
ExampleController
@EnableAutoConfiguration
@RestController
@RequestMapping({"/v2/"})
public class ExampleController {
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@RequestMapping(value = "/home", method = RequestMethod.GET)
String home() {
return "Hello World";
}
}
Whenever I try to access /v2/home using user:user
it executes just fine, shouldn't it give me an Access Denied error due to 'user' not having ROLE_ADMIN
?
I'm actually thinking of ditching access rules at method-level and stick to http() ant rules, but I have to know why it's not working for me.
I had a similar problem and the following solved it:
1) I had to make my method public (i.e. make your method home() public)
2) I have to use hasRole instead of hasAuthority
You have to add
@EnableGlobalMethodSecurity(prePostEnabled = true)
in your WebSecurityConfig.You can find it here: http://www.baeldung.com/spring-security-expressions-basic
For making it working on controller layer. I had to put @EnableAspectJAutoProxy on my configuration class. Example :
There are two different ways to use this, one is to prefix and one is not. And you maybe change
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
to@PreAuthorize("hasAuthority('ADMIN')")
will be ok.next is
@PreAuthorize
source code.If you have a xml context file for your security beans and a separate one for your web/servlet context, than you als need to add:
to your web-context.xml / servlet context. Its not enough to just add it in the security context xml.
Its not inherited in child contexts.
HTH
A common problem with using PrePost annotations on controllers is that Spring method security is based on Spring AOP, which is by default implemented with JDK proxies.
That means that it works fine on the service layer which is injected in controller layer as interfaces, but it is ignored on controller layer because controller generally do not implement interfaces.
The following is just my opinion: