I’m unable to use hasRole
method in @PreAuthorize
annotation. Also request.isUserInRole(“ADMIN”)
gives false
. What am I missing?
Although .hasAuthority(“ADMIN”)
works fine.
I am assigning authorities to the users from a database.
You have to name your authority with prefix ROLE_
to use isUserInRole
, see Spring Security Reference:
The HttpServletRequest.isUserInRole(String) will determine if
SecurityContextHolder.getContext().getAuthentication().getAuthorities()
contains aGrantedAuthority
with the role passed intoisUserInRole(String)
. Typically users should not pass in the "ROLE_" prefix into this method since it is added automatically. For example, if you want to determine if the current user has the authority "ROLE_ADMIN", you could use the following:boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");
Same for hasRole
(also hasAnyRole
), see Spring Security Reference:
Returns
true
if the current principal has the specified role. By default if the supplied role does not start with 'ROLE_' it will be added. This can be customized by modifying thedefaultRolePrefix
onDefaultWebSecurityExpressionHandler
.
I had to improvise a little, maybe there is other ways simpler then mine, but at the time I worked on this I had no other choice but to improvise a bit, after a thorough research came up with this solution.
Spring Security has an interface called AccessDecisionManager
, you will need to implement it.
@Component
public class RolesAccessDecisionManager implements AccessDecisionManager {
private final static String AUTHENTICATED = "authenticated";
private final static String PERMIT_ALL = "permitAll";
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
collection.forEach(configAttribute -> {
if (!this.supports(configAttribute))
throw new AccessDeniedException("ACCESS DENIED");
});
}
@Override
public boolean supports(ConfigAttribute configAttribute) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
String rolesAsString = authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));
if (configAttribute.toString().contains(rolesAsString))
return true;
else
return (configAttribute.toString().contains(PERMIT_ALL) || configAttribute.toString().contains(AUTHENTICATED));
}
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return true;
}
}
Now to support this custom access-decision-manager with your security config do this in the security configuration:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
// other configs
.accessDecisionManager(this.accessDecisionManager)
accessDecisionManager
is the autowired bean of the AccessDecisionManager
implementation you've created.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With