web-dev-qa-db-fra.com

Différence entre Role et GrantedAuthority dans Spring Security

Il existe des concepts et des implémentations dans Spring Security, tels que l'interface GrantedAuthority pour obtenir un autorité autorisant/contrôlant un accès.

Je voudrais que cela permette des opérations telles que createSubUsers, ou deleteAccounts, ce que je permettrais à un admin (avec le rôle ROLE_ADMIN).

Je suis en train de me perdre dans les tutoriels/démonstrations que je vois en ligne. J'essaie de relier ce que j'ai lu, mais je pense que nous traitons les deux de manière interchangeable.

Je vois hasRole consommer une chaîne GrantedAuthority? Je le fais très certainement mal dans la compréhension. Que sont-ils conceptuellement dans Spring Security?

Comment enregistrer le rôle d'un utilisateur, distinct des autorités pour ce rôle?

Je regarde également l'interface org.springframework.security.core.userdetails.UserDetails qui est utilisée dans le DAO référencé par le fournisseur d'authentification, qui consomme un User (notez le dernier attribut GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

Ou existe-t-il un autre moyen de différencier les deux autres? Ou n'est-ce pas pris en charge et nous devons créer le nôtre?

200
Chinmay

Pensez à une autorité accordée comme une "permission" ou un "droit". Ces "permissions" sont (normalement) exprimées sous forme de chaînes (avec la méthode getAuthority()). Ces chaînes vous permettent d'identifier les autorisations et de laisser vos électeurs décider s'ils accordent l'accès à quelque chose.

Vous pouvez accorder différentes autorisations (autorisations) aux utilisateurs en les plaçant dans le contexte de sécurité. Pour ce faire, vous devez normalement implémenter votre propre UserDetailsService qui renvoie une implémentation UserDetails renvoyant les droits GrantedAuthorities nécessaires.

Les rôles (tels qu'ils sont utilisés dans de nombreux exemples) ne sont que des "autorisations" avec une convention de dénomination qui dit qu'un rôle est une GrantedAuthority qui commence par le préfixe ROLE_. Il n'y a plus rien. Un rôle est juste un GrantedAuthority - une "permission" - un "droit". Vous voyez de nombreux endroits dans la sécurité de printemps où le rôle avec son préfixe ROLE_ est traité spécialement comme par exemple. dans RoleVoter, où le préfixe ROLE_ est utilisé par défaut. Cela vous permet de fournir les noms de rôle sans le préfixe ROLE_. Avant Spring, le traitement spécial des "rôles" n’était pas suivi de manière très uniforme et les autorités et les rôles étaient souvent traités de la même manière (comme vous pouvez le voir, par exemple, dans la mise en oeuvre de la méthode hasAuthority() dans SecurityExpressionRoot - qui appelle simplement hasRole()). Avec Spring Security 4, le traitement des rôles est plus cohérent et le code qui traite des "rôles" (comme l'expression RoleVoter, l'expression hasRole, etc.) ajoute toujours le préfixe ROLE_. . Donc, hasAuthority('ROLE_ADMIN') signifie la même chose que hasRole('ADMIN') parce que le préfixe ROLE_ est ajouté automatiquement. Voir la note de sécurité 3 à 4 du printemps guide de migration pour plus d'informations.

Mais encore: un rôle est juste une autorité avec un préfixe ROLE_ spécial. Donc, dans Spring Security 3 @PreAuthorize("hasRole('ROLE_XYZ')") est identique à @PreAuthorize("hasAuthority('ROLE_XYZ')") et dans Spring Security 4 @PreAuthorize("hasRole('XYZ')") est identique à @PreAuthorize("hasAuthority('ROLE_XYZ')").

En ce qui concerne votre cas d'utilisation:

Les utilisateurs ont des rôles et les rôles peuvent effectuer certaines opérations.

Vous pouvez vous retrouver dans GrantedAuthorities pour les rôles auxquels un utilisateur appartient et pour les opérations qu'un rôle peut effectuer. Les GrantedAuthorities des rôles ont le préfixe ROLE_ et les opérations ont le préfixe OP_. Un exemple pour les autorités d'exploitation pourrait être OP_DELETE_ACCOUNT, OP_CREATE_USER, OP_RUN_BATCH_JOBetc. Les rôles peuvent être ROLE_ADMIN, ROLE_USER, etc.

Vous pourriez finir par avoir vos entités implémenter GrantedAuthority comme dans cet exemple (pseudo-code):

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @OneToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @OneToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}

Les identifiants des rôles et des opérations que vous créez dans votre base de données seraient la représentation GrantedAuthority, par exemple. "ROLE_ADMIN", "OP_DELETE_ACCOUNT" etc. Lorsqu'un utilisateur est authentifié, assurez-vous que toutes les attributions GrantedAuthorities, ainsi que les opérations correspondantes, sont renvoyées à partir de la méthode UserDetails.getAuthorities ().

Exemple: le rôle admin portant l'ID ROLE_ADMIN est affecté aux opérations OP_DELETE_ACCOUNT, OP_READ_ACCOUNT et OP_RUN_BATCH_JOB. Le rôle d'utilisateur portant l'ID ROLE_USER a l'opération OP_READ_ACCOUNT.

Si un administrateur se connecte dans le contexte de sécurité résultant, aura les droits accordés suivants: ROLE_ADMIN, OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOB.

Si un utilisateur le connecte, il aura: ROLE_USER, OP_READ_ACCOUNT

UserDetailsService veillera à collecter tous les rôles et toutes les opérations de ces rôles et à les rendre disponibles à l'aide de la méthode getAuthorities () dans l'instance UserDetails renvoyée.

320
James

Autant que je sache, l'autorité et les rôles sont les mêmes dans la sécurité du printemps. La chaîne getAuthority () de GrantedAuthority est le rôle (selon l'implémentation par défaut SimpleGrantedAuthority).

Pour votre cas, vous pouvez utiliser des rôles hiérarchiques

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>

Pas exactement le sol que vous cherchez, mais j'espère que cela vous aidera

Edit: Répondre à votre commentaire

Le rôle est comme une permission dans Spring-Security. utiliser intercept-url avec hasRole fournit un contrôle très précis de l'opération autorisée pour quel rôle/autorisation.

La manière dont nous traitons notre application est la suivante: nous définissons une autorisation (c'est-à-dire un rôle) pour chaque opération (ou une URL de repos) pour, par exemple. view_account, delete_account, add_account etc. Nous créons ensuite des profils logiques pour chaque utilisateur, tels que admin, guest_user, normal_user. Les profils ne sont que des groupements logiques d'autorisations, indépendants de Spring-Security. Lorsqu'un nouvel utilisateur est ajouté, un profil lui est attribué (disposant de toutes les autorisations autorisées). Désormais, chaque fois que l'utilisateur essaie d'exécuter une action, l'autorisation/le rôle de cette action est vérifié par rapport aux droits accordés à l'utilisateur.

De plus, defaultn RoleVoter utilise le préfixe ROLE_. Par conséquent, toute autorité commençant par ROLE_ est considérée comme un rôle. Vous pouvez modifier ce comportement par défaut en utilisant un préfixe de rôle personnalisé dans le rôle du votant et son utilisation dans la sécurité Spring.

7
coder

Une autre façon de comprendre la relation entre ces concepts consiste à interpréter un rôle comme un conteneur d’autorités.

Les autorités sont des autorisations précises ciblant une action spécifique, parfois couplées à une étendue de données ou à un contexte spécifique. Par exemple, Lecture, Écriture, Gestion peuvent représenter différents niveaux d’autorisations pour une étendue donnée d’informations.

De plus, les autorités sont imposées profondément dans le flux de traitement d'une demande, tandis que ROLE est filtré par le filtre de requête avant d'atteindre le contrôleur. Les meilleures pratiques recommandent de mettre en œuvre l'application des autorités par rapport au contrôleur dans la couche de gestion.

D'autre part, les ROLES sont une représentation à grains grossiers d'un ensemble d'autorisations. Un ROLE_READER aurait uniquement l'autorité de lecture ou d'affichage, tandis qu'un ROLE_EDITOR aurait à la fois la lecture et l'écriture. Les rôles sont principalement utilisés pour une première analyse à la périphérie du traitement de la demande, telle que http. ... .antMatcher (...). hasRole (ROLE_MANAGER)

Les autorités appliquées au plus profond du flux de processus de la demande permettent une application plus fine de l'autorisation. Par exemple, un utilisateur peut avoir l'autorisation de lecture/écriture pour mettre au premier niveau une ressource, mais uniquement la lecture sur une sous-ressource. Avoir un ROLE_READER restreindrait son droit de modifier la ressource de premier niveau car il a besoin de l'autorisation en écriture pour modifier cette ressource, mais un intercepteur @PreAuthorize pourrait bloquer sa tentative de modification de la sous-ressource.

Jake

3
softjake