I want to have the ability to grant different authorities to users depending on which resource they're attempting to access. Of course, I could do this by implementing logic in each of the relevant controllers, but I would really like to take advantage of the Thymeleaf security extras in my templates, as well as Spring's @PreAuthorize()
annotations.
As of right now I am using a simple implementation of a UserDetails
to provide a list of granted authorities from some models in a database:
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.userAccount.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
However, I want behavior that can do the following:
User requests
/courses/1
. They're a student in that course, so they get these roles: (...)User requests
/courses/2
. They're an admin in that course, so they get these roles: (...)
The problem is that Spring's UserDetailService
and UserDetails
interfaces don't allow for auto-wiring the context's current request anywhere, as far as I can see. Is there any way that this can be done? Ideally I'd just want access to the HttpServletRequest
. Something like this:
@Override
public Collection<? extends GrantedAuthority> getAuthorities(HttpServetRequest request) {
return this.userAccount.getRolesForURI(request.getURI()).stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
You can simply @Autowire the HttpServletRequest into your UserDetailsService.
@Autowired
private HttpServletRequest request;
For it to work you might need to register a RequestContextListener.
@Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}