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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3021200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:39:39  来源:igfitidea点击:

How to check "hasRole" in Java Code with Spring Security?

javaspring-securityuser-roles

提问by Piotr Gwiazda

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:

如何在 Java 代码中检查用户权限或权限?例如 - 我想根据角色为用户显示或隐藏按钮。有这样的注释:

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

How to make it in Java code? Something like :

如何在Java代码中制作它?就像是 :

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

采纳答案by JoseK

Spring Security 3.0 has this API

Spring Security 3.0 有这个 API

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

You'll have to inject the wrapper, before you use it.

在使用它之前,您必须注入包装器。

SecurityContextHolderAwareRequestWrapper

SecurityContextHolderAwareRequestWrapper

回答by Sean Patrick Floyd

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 DefaultMethodSecurityExpressionHandlerto see if you can re-use something they are doing there

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

回答by gouki

you can use the isUserInRole method of the HttpServletRequest object.

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

something like:

就像是:

public String createForm(HttpSession session, HttpServletRequest request,  ModelMap   modelMap) {


    if (request.isUserInRole("ROLE_ADMIN")) {
        // code here
    }
}

回答by Gopi

You can implement a hasRole() method as below - (This is tested on spring security 3.0.x not sure about other versions.)

您可以实现如下的 hasRole() 方法 - (这是在 spring security 3.0.x 上测试的,不确定其他版本。)

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

回答by lukec

Better late then never, let me put in my 2 cents worth.

迟到总比没有好,让我投入我的 2 美分。

In JSF world, within my managed bean, I did the following:

在 JSF 世界中,在我的托管 bean 中,我执行了以下操作:


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

回答by Starman

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.

当您在您的服务层中时,无法使用 JoseK 的答案,您不希望从引用到 HTTP 请求引入与 web 层的耦合。如果您正在考虑解决服务层中的角色,Gopi 的答案就是要走的路。

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

回答by Joey Jarin

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

回答by Nate Sammons

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

回答by Ninca

Instead of using a loop to find the authority from UserDetails you can do:

您可以执行以下操作,而不是使用循环从 UserDetails 中查找权限:

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

回答by JonnyRaa

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("blah") 时,并没有太多说明你实际检查的内容

HasRole checks the granted authorities for the currently authenticated principal

HasRole 检查当前已验证主体的授予权限

So really when you see hasRole("blah") really means hasAuthority("blah").

所以当你看到hasRole("blah") 真的意味着 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.

在我看到的情况下,您使用一个实现 UserDetails 的类来执行此操作,该类定义了一个名为 getAuthorities 的方法。在这里,您基本上将new SimpleGrantedAuthority("some name")根据某些逻辑将一些添加到列表中。此列表中的名称是由 hasRole 语句检查的内容。

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.

我猜在这种情况下 UserDetails 对象是当前经过身份验证的主体。身份验证提供程序内部和周围发生了一些神奇的事情,更具体地说,身份验证管理器使这一切发生了。