Question

Comment vérifier l'autorité d'utilisateur ou permission du code Java? Par exemple - je veux montrer ou bouton de masquage pour l'utilisateur en fonction de rôle. Il y a des annotations comme:

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

Comment faire dans le code Java? Quelque chose comme:

if(somethingHere.hasRole("ROLE_MANAGER")) {
   layout.addComponent(new Button("Edit users"));
}
Était-ce utile?

La solution

Spring Security 3.0 a cette API

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

Vous devrez injecter l'emballage, avant de l'utiliser.

SecurityContextHolderAwareRequestWrapper

Autres conseils

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

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

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

Vous pouvez récupérer le contexte de sécurité et de l'utiliser ensuite:

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

Vous pouvez mettre en œuvre une méthode hasRole () comme ci-dessous - (. Ceci est testé sur 3.0.x de sécurité du ressort pas sûr d'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;
  }

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

La réponse de josek ne peut pas être utilisé lorsque votre 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 êtes à la recherche dans la résolution des rôles alors que dans la couche de service, la réponse de Gopi est le chemin à parcourir.

Cependant, il est un peu longue haleine. Les autorités sont accessibles directement depuis 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;
}

La plupart des réponses manquent quelques points:

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

  2. Les noms de rôle sont égaux à rolePrefix + authority.

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

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

Malheureusement, la personnalisation du préfixe rôle au printemps 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ée dans le contexte du printemps, et si elle existe, le rôle personnalisé préfixer a est respecté.

Apporter toutes ces informations, une meilleure mise en œuvre du vérificateur de rôle 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);
    }
}

La réponse @gouki est le meilleur!

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

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

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

SecurityContextHolderAwareRequestWrapper le code est comme:

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

Cette annotation deux ci-dessous est égal, "hasRole" volonté préfixe add auto "ROLE_". Assurez-vous que vous avez l'annotation droite. Ce rôle est défini dans UserDetailsService # loadUserByUsername.

@PreAuthorize("hasAuthority('ROLE_user')")
@PreAuthorize("hasRole('user')")

alors, vous pouvez obtenir le rôle dans le code java.

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){
    System.out.println("user role2");
}

est une sorte de venir à la question de l'autre bout, mais je pensais que je jetterais dans comme je l'avais vraiment creuser sur Internet pour trouver cela.

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 en fait quand vous dites hasRole ( « bla »)

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

authentifié

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

Dans le cas, je l'ai vu, vous le faites avec une classe implémentant UserDetails qui définit une méthode appelée getAuthorities. En cela, vous allez essentiellement ajouter certains new SimpleGrantedAuthority("some name") à une liste basée sur une certaine logique. Les noms de cette liste sont les choses vérifiées par les déclarations hasRole.

Je suppose que dans ce contexte, l'objet de UserDetails est le principal actuellement authentifié. Il y a quelque chose de magique qui se passe dans et autour des fournisseurs d'authentification et plus particulièrement le gestionnaire d'authentification qui fait arriver.

Dans notre projet, nous utilisons une hiérarchie des rôles, alors que la plupart des réponses ci-dessus visent uniquement à vérifier pour un rôle spécifique, ce serait seulement vérifier le rôle donné, mais pas pour ce rôle et la hiérarchie.

solution A 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 haricot au printemps-security.xml.

Mon approche avec l'aide de Java 8, passage séparés par des virgules rôles vous donnera vrai ou faux

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

Sur votre modèle utilisateur ajouter juste une méthode « hasRole » comme ci-dessous

public boolean hasRole(String auth) {
    for (Role role : roles) {
        if (role.getName().equals(auth)) { return true; }
    }
    return false;
}

Je l'habitude d'utiliser pour vérifier si l'utilisateur authentifié a l'administrateur de rôle comme suit

Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // This gets the authentication
User authUser = (User) authentication.getPrincipal(); // This gets the logged in user
authUser.hasRole("ROLE_ADMIN") // This returns true or false
scroll top