Comment vérifier "hasRole" dans le Code Java avec Spring Security?

Comment vérifier l'autorité ou l'autorisation de l'utilisateur dans le Code Java ? Par exemple je veux afficher ou masquer le bouton pour l'utilisateur en fonction du rôle. Il y a des annotations comme:

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

Comment le faire en code Java? Quelque chose comme:

if(somethingHere.hasRole("ROLE_MANAGER")) {
   layout.addComponent(new Button("Edit users"));
}
102
demandé sur Gajanan Kulkarni 2010-06-11 12:12:40

16 réponses

66
répondu JoseK 2016-09-20 13:41:51

Vous pouvez utiliser la méthode isUserInRole de L'objet HttpServletRequest.

Quelque Chose comme:

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


    if (request.isUserInRole("ROLE_ADMIN")) {
        // code here
    }
}
119
répondu gouki 2010-06-23 08:32:21

Au Lieu d'utiliser une boucle pour trouver l'autorité de UserDetails vous pouvez faire:

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
53
répondu Ninca 2015-02-13 09:24:13

Vous pouvez récupérer le contexte de sécurité, puis l'utiliser:

    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;
    }
41
répondu Nate Sammons 2012-04-19 16:27:27

Vous pouvez implémenter une méthode hasRole () comme ci - dessous - (Ceci est testé sur spring security 3.0.x Pas sûr des autres 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;
  }
13
répondu Gopi 2010-08-05 06:10:09

J'utilise ceci:

@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);
}
9
répondu Joey Jarin 2012-11-10 07:42:51

La réponse de JoseK ne peut pas être utilisée lorsque vous êtes dans votre couche de service, où vous ne voulez pas introduire un couplage avec la couche web à partir de la référence à la requête HTTP. Si vous envisagez de résoudre les rôles dans la couche de service, la réponse de Gopi est la voie à suivre.

Cependant, il est un peu longue haleine. Les autorités sont accessibles directement à partir de L'authentification. Par conséquent, si vous pouvez supposer que vous avez un utilisateur connecté, ce qui suit le fait:

/**
 * @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;
}
5
répondu Starman 2010-10-08 15:40:13

Curieusement, je ne pense pas qu'il existe une solution standard à ce problème, car le contrôle d'accès spring-security est basé sur l'expression, pas basé sur java. vous pouvez vérifier le code source de DefaultMethodSecurityExpressionHandler pour voir si vous pouvez réutiliser quelque chose qu'ils font là

2
répondu Sean Patrick Floyd 2010-06-11 08:34:35

Mieux vaut tard que jamais, laissez-moi mettre mes 2 cents de valeur.

Dans JSF world, dans mon bean géré, j'ai fait ce qui suit:


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

Comme mentionné ci-dessus, ma compréhension est que cela peut être fait de la manière longue comme suit:


Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
    userDetails = (UserDetails) principal;
    Collection  authorities = userDetails.getAuthorities();
}
2
répondu lukec 2010-09-22 01:25:41

Cela vient en quelque sorte à la question de l'autre bout, mais je pensais que je le jetterais car je devais vraiment creuser sur internet pour le savoir.

Il y a beaucoup de choses sur la façon de vérifier les rôles, mais pas beaucoup dire ce que vous vérifiez réellement quand vous dites hasRole ("blah")

HasRole vérifie les autorisations accordées pour le principal authentifié

Alors, vraiment, quand vous voyez hasRole("bla") signifie vraiment hasAuthority("bla").

Dans le cas que j'ai vu, vous le faites avec une classe qui implémente UserDetails qui définit une méthode appelée getAuthorities. En cela, vous allez essentiellement Ajouter new SimpleGrantedAuthority("some name") à une liste basée sur une logique. Les noms dans cette liste sont les choses vérifiées par les instructions hasRole.

Je suppose que dans ce contexte, L'objet UserDetails est le principal actuellement authentifié. Il y a une certaine magie qui se produit dans et autour des fournisseurs d'authentification et plus encore plus précisément, le gestionnaire d'authentification qui rend cela possible.

1
répondu Jonny Leeds 2014-06-03 10:54:40

La réponse @ gouki est la meilleure!

Juste un conseil de la façon dont le printemps fait vraiment cela.

Il existe une classe nommée SecurityContextHolderAwareRequestWrapper qui implémente la classe ServletRequestWrapper.

Le SecurityContextHolderAwareRequestWrapper remplace le isUserInRole et recherche Utilisateur Authentication (qui est géré par Spring) pour trouver si l'Utilisateur a un rôle ou non.

SecurityContextHolderAwareRequestWrapper le code est:

    @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;
    }
1
répondu Alireza Fattahi 2014-12-08 15:33:31

Vous pouvez obtenir de l'aide de la classe AuthorityUtils. Vérification du rôle en tant que One-liner:

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

Mise en garde: cela ne vérifie pas la hiérarchie des rôles, si elle existe.

1
répondu holmis83 2017-08-07 08:15:07

La plupart des réponses manquent quelques points:

  1. Rôle et l'autorité ne sont pas la même chose au Printemps. Voir ici pour plus détails.

  2. Les noms de rôles sont égales à rolePrefix + authority.

  3. Le préfixe de rôle par défaut est ROLE_, cependant, il est configurable. Voir ici.

Par conséquent, une vérification de rôle appropriée doit respecter le préfixe de rôle s'il est configuré.

Malheureusement, la personnalisation du préfixe de rôle dans Spring est un peu hacky, dans de nombreux endroits, le préfixe par défaut, ROLE_ est codé en dur, mais en plus de cela, un bean de type GrantedAuthorityDefaults est vérifié dans le contexte Spring, et s'il existe, le préfixe de rôle personnalisé qu'il a est respecté.

En rassemblant toutes ces informations, une meilleure implémentation du vérificateur de rôles serait quelque chose comme:

@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);
    }
}
1
répondu Utku Özdemir 2017-11-16 01:58:10

Dans notre projet, nous utilisons une hiérarchie de rôles, alors que la plupart des réponses ci-dessus ne visent qu'à vérifier un rôle spécifique, c'est-à-dire ne vérifieraient que le rôle donné, mais pas ce rôle et la hiérarchie.

Une solution pour cela:

@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 est défini comme un bean dans spring-security.XML.

0
répondu Kirinya 2016-08-25 09:57:00

Mon approche avec L'aide de Java8, en passant des rôles séparés par coma vous donnera true ou 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;
}
0
répondu Jajikanth pydimarla 2018-06-19 20:08:58

Pour vérifier le rôle de l'utilisateur, vous pouvez essayer ceci:

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

Puis :

if(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN))
    {
    `enter code here`
    }
0
répondu miguelk5 2018-09-07 07:35:31