可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How to check user authority or permission in Java Code ? For example - I want to show or hide button for user depending on role. There are annotations like:
@PreAuthorize("hasRole('ROLE_USER')")
How to make it in Java code? Something like :
if(somethingHere.hasRole("ROLE_MANAGER")) {
layout.addComponent(new Button("Edit users"));
}
回答1:
Spring Security 3.0 has this API
SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)
You'll have to inject the wrapper, before you use it.
SecurityContextHolderAwareRequestWrapper
回答2:
you can use the isUserInRole method of the HttpServletRequest object.
something like:
public String createForm(HttpSession session, HttpServletRequest request, ModelMap modelMap) {
if (request.isUserInRole("ROLE_ADMIN")) {
// code here
}
}
回答3:
Instead of using a loop to find the authority from UserDetails you can do:
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
回答4:
You can retrieve the security context and then use that:
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
protected boolean hasRole(String role) {
// get security context from thread local
SecurityContext context = SecurityContextHolder.getContext();
if (context == null)
return false;
Authentication authentication = context.getAuthentication();
if (authentication == null)
return false;
for (GrantedAuthority auth : authentication.getAuthorities()) {
if (role.equals(auth.getAuthority()))
return true;
}
return false;
}
回答5:
You can implement a hasRole() method as below - (This is tested on spring security 3.0.x not sure about other versions.)
protected final boolean hasRole(String role) {
boolean hasRole = false;
UserDetails userDetails = getUserDetails();
if (userDetails != null) {
Collection<GrantedAuthority> authorities = userDetails.getAuthorities();
if (isRolePresent(authorities, role)) {
hasRole = true;
}
}
return hasRole;
}
/**
* Get info about currently logged in user
* @return UserDetails if found in the context, null otherwise
*/
protected UserDetails getUserDetails() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
userDetails = (UserDetails) principal;
}
return userDetails;
}
/**
* Check if a role is present in the authorities of current user
* @param authorities all authorities assigned to current user
* @param role required authority
* @return true if role is present in list of authorities assigned to current user, false otherwise
*/
private boolean isRolePresent(Collection<GrantedAuthority> authorities, String role) {
boolean isRolePresent = false;
for (GrantedAuthority grantedAuthority : authorities) {
isRolePresent = grantedAuthority.getAuthority().equals(role);
if (isRolePresent) break;
}
return isRolePresent;
}
回答6:
I'm using this:
@RequestMapping(method = RequestMethod.GET)
public void welcome(SecurityContextHolderAwareRequestWrapper request) {
boolean b = request.isUserInRole("ROLE_ADMIN");
System.out.println("ROLE_ADMIN=" + b);
boolean c = request.isUserInRole("ROLE_USER");
System.out.println("ROLE_USER=" + c);
}
回答7:
The answer from JoseK can't be used when your in your service layer, where you don't want to introduce a coupling with the web layer from the reference to the HTTP request. If you're looking into resolving the roles while in the service layer, Gopi's answer is the way to go.
However, it's a bit long winded. The authorities can be accessed right from the Authentication. Hence, if you can assume that you have a user logged in, the following does it:
/**
* @return true if the user has one of the specified roles.
*/
protected boolean hasRole(String[] roles) {
boolean result = false;
for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
String userRole = authority.getAuthority();
for (String role : roles) {
if (role.equals(userRole)) {
result = true;
break;
}
}
if (result) {
break;
}
}
return result;
}
回答8:
You can get some help from AuthorityUtils class. Checking role as a one-liner:
if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) {
/* ... */
}
Caveat: This does not check role hierarchy, if such exists.
回答9:
Strangely enough, I don't think there is a standard solution to this problem, as the spring-security access control is expression based, not java-based. you might check the source code for
DefaultMethodSecurityExpressionHandler to see if you can re-use something they are doing there
回答10:
Better late then never, let me put in my 2 cents worth.
In JSF world, within my managed bean, I did the following:
HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, "");
As mentioned above, my understanding is that it can be done the long winded way as followed:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
userDetails = (UserDetails) principal;
Collection authorities = userDetails.getAuthorities();
}
回答11:
Most answers are missing some points:
Role and authority are not the same thing in Spring. See here for more details.
Role names are equal to rolePrefix
+ authority
.
The default role prefix is ROLE_
, however, it is configurable. See here.
Therefore, a proper role check needs to respect the role prefix if it is configured.
Unfortunately, the role prefix customization in Spring is a bit hacky, in many places the default prefix, ROLE_
is hardcoded, but in addition to that, a bean of type GrantedAuthorityDefaults
is checked in the Spring context, and if it exists, the custom role prefix it has is respected.
Bringing all this information together, a better role checker implementation would be something like:
@Component
public class RoleChecker {
@Autowired(required = false)
private GrantedAuthorityDefaults grantedAuthorityDefaults;
public boolean hasRole(String role) {
String rolePrefix = grantedAuthorityDefaults != null ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
.map(Authentication::getAuthorities)
.map(Collection::stream)
.orElse(Stream.empty())
.map(GrantedAuthority::getAuthority)
.map(authority -> rolePrefix + authority)
.anyMatch(role::equals);
}
}
回答12:
This is sort of coming at the question from the other end but I thought I'd throw it in as I really had to dig on the internet to find this out.
There is a lot of stuff about how to check roles but not much saying what you are actually checking when you say hasRole("blah")
HasRole checks the granted authorities for the currently authenticated principal
So really when you see hasRole("blah") really means hasAuthority("blah").
In the case I've seen, you do this with a class that Implements UserDetails which defines a method called getAuthorities. In this you'll basically add some new SimpleGrantedAuthority("some name")
to a list based on some logic. The names in this list are the things checked by the hasRole statements.
I guess in this context the UserDetails object is the currently authenticated principal. There's some magic that happens in and around authentication providers and more specifically the authentication-manager that makes this happen.
回答13:
The @gouki answer is best!
Just a tip of how spring really do this.
There is a class named SecurityContextHolderAwareRequestWrapper
which implements the ServletRequestWrapper
class.
The SecurityContextHolderAwareRequestWrapper
overrides the isUserInRole
and search user Authentication
(which is managed by Spring) to find if user has a role or not.
SecurityContextHolderAwareRequestWrapper
the code is as:
@Override
public boolean isUserInRole(String role) {
return isGranted(role);
}
private boolean isGranted(String role) {
Authentication auth = getAuthentication();
if( rolePrefix != null ) {
role = rolePrefix + role;
}
if ((auth == null) || (auth.getPrincipal() == null)) {
return false;
}
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
if (authorities == null) {
return false;
}
//This is the loop which do actual search
for (GrantedAuthority grantedAuthority : authorities) {
if (role.equals(grantedAuthority.getAuthority())) {
return true;
}
}
return false;
}
回答14:
To check user role you can try this:
public static boolean isCurrentUserInRole(String authority) {
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
if (authentication != null) {
return authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority));
}
return false;
}
and then :
if(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN))
{
`enter code here`
}
回答15:
In our project, we are using a role hierarchy, while most of the above answers only aim at checking for a specific role, i.e. would only check for the role given, but not for that role and up the hierarchy.
A solution for this:
@Component
public class SpringRoleEvaluator {
@Resource(name="roleHierarchy")
private RoleHierarchy roleHierarchy;
public boolean hasRole(String role) {
UserDetails dt = AuthenticationUtils.getSessionUserDetails();
for (GrantedAuthority auth: roleHierarchy.getReachableGrantedAuthorities(dt.getAuthorities())) {
if (auth.toString().equals("ROLE_"+role)) {
return true;
}
}
return false;
}
RoleHierarchy is defined as a bean in spring-security.xml.
回答16:
My Approach with the help of Java8 , Passing coma separated roles will give you true or false
public static Boolean hasAnyPermission(String permissions){
Boolean result = false;
if(permissions != null && !permissions.isEmpty()){
String[] rolesArray = permissions.split(",");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
for (String role : rolesArray) {
boolean hasUserRole = authentication.getAuthorities().stream().anyMatch(r -> r.getAuthority().equals(role));
if (hasUserRole) {
result = true;
break;
}
}
}
return result;
}