I am trying to set up a method security annotation using @Secured("ADMIN") (without any XML, only java config, Spring Boot). But access via roles does not work.
Security Config:
@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
.....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated().and()
.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
.....
}
I want restrict access to the method of the controller:
@RestController
@RequestMapping("/api/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@Secured("ADMIN")
@RequestMapping
public List<Group> list() {
return groupService.findAll();
}
}
Restrict access by the url is working, with:
.antMatchers("/api/**").hasAuthority("ADMIN")
Maybe I forgot to specify that I want restrict by roles?
UPD:
By the rules, At what layer must be @PreAuthorize("hasRole('ADMIN')")
in Controller layer or in Service layer?
This issue was solved.
I add
@EnableGlobalMethodSecurity(prePostEnabled = true)
And in controller i changed
@Secured("ADMIN")
to@PreAuthorize("hasRole('ADMIN')")
I want to share my decision, may be it will be helpful.
Used spring mvc + spring security, version
4.2.9.RELEASE
For example, i have a Service with method annotated @Secured
But, it didn't work, because GlobalMethodSecurityConfiguration has inside method.
in which initialized the
new RoleVoter()
with defaultrolePrefix = "ROLE_";
(this makes it impossible to use beans to set your rolePrefix) that give to us not working annotations, because RoleVoter expects annotation value which starts with 'ROLE_'For resolving this problem i override GlobalMethodSecurityConfiguration like this
Maybe you should register your AppSecurityConfiguration to same context as WebMvcConfig (that extends WebMvcConfigurerAdapter).
You need to use @secured(ROLE_ADMIN) instead of @secured(ADMIN). You are required to write "ROLE_" infront of your role name. Please find the example mentioned below which is making sure only a user with Admin role can access list() method.
There may be many reasons for which method security on a controller does not work.
First because it is never cited as example in Spring Security manual ... joking but it may be tricky to take Spring tools where they do not want to go.
More seriously, you should enable method security as already said by @Mudassar. The manual says :
We can enable annotation-based security using the
@EnableGlobalMethodSecurity
annotation on any@Configuration
instance. For example, the following would enable Spring Security’s@Secured
annotation.Note that Mudassar's answer is correct till here.
But method security is based on AOP, which by default uses JDK proxying on interfaces. That's the reason why all examples applies method security on the service layer, because the service classes are normally injected in controllers as interfaces.
You can of course use it on controller layer, but :
@Secured
annotated methodsThe rule that I try to follow is :
Kindly add this
This element is used to enable annotation-based security in your application (by setting the appropriate attributes on the element), and also to group together security pointcut declarations which will be applied across your entire application context specifically for
@Secured
. Hence your code should look like this