如何使用Spring Security在Java代码中检查“hasRole”?

如何检查Java代码中的用户权限或权限? 例如 – 我想根据angular色显示或隐藏用户的button。 有如下注释:

@PreAuthorize("hasRole('ROLE_USER')") 

如何使用Java代码? 就像是 :

 if(somethingHere.hasRole("ROLE_MANAGER")) { layout.addComponent(new Button("Edit users")); } 

您可以使用HttpServletRequest对象的isUserInRole方法。

就像是:

 public String createForm(HttpSession session, HttpServletRequest request, ModelMap modelMap) { if (request.isUserInRole("ROLE_ADMIN")) { // code here } } 

而不是使用循环来从UserDetails中find权限,你可以这样做:

 Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN")); 

您可以检索安全上下文,然后使用它:

  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; } 

你可以像下面那样实现一个hasRole()方法 – (这是在Spring 3.0.x上testing的,不知道其他版本)

  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; } 

我正在使用这个:

 @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); } 

来自JoseK的答案不能用在你的服务层,在那里你不想引入与HTTP请求引用的web层的耦合。 如果您正在寻求解决服务层中的angular色问题,Gopi的答案就是要走的路。

但是,这有点长。 可以从authentication中直接访问权限。 因此,如果你可以假设你有一个用户login,下面是它:

 /** * @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; } 

奇怪的是,我不认为这个问题有一个标准的解决scheme,因为spring-security访问控制是基于expression式的 ,而不是基于java的。 你可以检查DefaultMethodSecurityExpressionHandler的源代码,看看你是否可以重用他们正在做的事情

再晚一点,永远不要,让我把我的2美分价值。

在JSF世界里,在我的托pipebean中,我做了以下操作:

 HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, ""); 

如上所述,我的理解是,可以做到这一点:

 Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); UserDetails userDetails = null; if (principal instanceof UserDetails) { userDetails = (UserDetails) principal; Collection authorities = userDetails.getAuthorities(); } 

@gouki答案是最好的!

只是spring真的这样做的一angular。

有一个名为SecurityContextHolderAwareRequestWrapper的类实现了ServletRequestWrapper类。

SecurityContextHolderAwareRequestWrapper覆盖isUserInRole和search用户Authentication (由Springpipe理)来查找用户是否有angular色。

SecurityContextHolderAwareRequestWrapper的代码是这样的:

  @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; } 

这是来自另一端的问题,但我想我会把它扔进去,因为我真的不得不在互联网上挖掘出来。

有很多关于如何检查angular色的内容,但是当你说hasRole(“blah”)

HasRole检查当前authentication的委托人授予的权限

所以当你看到hasRole(“blah”)真的意味着hasAuthority(“blah”)

在我看到的情况下,您可以使用一个实现UserDetails的类来完成此操作,该类定义了一个名为getAuthorities的方法。 在这个基本上,你将基本上添加一些new SimpleGrantedAuthority("some name")到一个基于一些逻辑的列表。 这个列表中的名字是由hasRole语句检查的东西。

我猜在这种情况下,UserDetails对象是当前authentication的主体。 在身份validation提供程序中及其周围发生了一些魔术,更具体地说是发生这种情况的身份validationpipe理器。

在我们的项目中,我们使用的是一个angular色层次结构,而上面的大多数答案只是针对特定angular色的检查,即只检查给定的angular色,而不检查angular色和层次结构。

这个解决scheme:

 @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在spring-security.xml中定义为一个bean。

你可以从AuthorityUtils类获得一些帮助。 检查angular色作为一个单线:

 if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) { /* ... */ } 

注意:这不检查angular色层次结构,如果存在的话。

大多数答案都缺less一些观点:

  1. 在spring,angular色和权威是不一样的。 在这里看到更多的细节。

  2. angular色名称等于rolePrefix + authority

  3. 默认的angular色前缀是ROLE_ ,但是它是可configuration的。 看到这里 。

因此,一个合适的angular色检查需要尊重angular色前缀,如果configuration。

不幸的是,Spring中的angular色前缀自定义有点冒失,在很多地方默认的前缀ROLE_是硬编码的,除此之外,在Spring上下文中检查了一个GrantedAuthorityDefaultstypes的bean,如果存在,自定义angular色它的前缀是被尊重的。

将所有这些信息汇总在一起,一个更好的angular色检查器实现将是这样的:

 @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); } }