web-dev-qa-db-fra.com

Spring Security avec des rôles et des autorisations

J'essaie de configurer la sécurité basée sur les rôles avec des autorisations. J'essaie de faire cela avec Spring-Security.

Je ne veux pas configurer ACL car il semble que ce soit une surcharge pour mes besoins.

Je veux juste avoir des permissions et des rôles simples comme décrit dans ce article . Malheureusement, l'article ne décrit pas comment implémenter la solution donnée.

Est-ce que quelqu'un a déjà essayé et peut me diriger dans la bonne direction? Peut-être existe-t-il une autre entrée de blog décrivant la mise en œuvre?

Merci beaucoup.

76
flash

Pour mettre en œuvre cela, il semble que vous deviez:

  1. Créez votre modèle (utilisateur, rôle, autorisations) et un moyen de récupérer les autorisations pour un utilisateur donné;
  2. Définissez votre propre org.springframework.security.authentication.ProviderManager et configurez-le (définissez ses fournisseurs) sur un org.springframework.security.authentication.AuthenticationProvider. Ce dernier devrait renvoyer sur sa méthode d’authentification une authentification, qui devrait être configurée avec le org.springframework.security.core.GrantedAuthority, dans votre cas, toutes les autorisations pour l'utilisateur donné.

Le truc dans cet article est d’attribuer des rôles aux utilisateurs, mais de définir les autorisations pour ces rôles dans le Authentication.authorities objet.

Pour cela, je vous conseille de lire l'API et de voir si vous pouvez étendre certains ProviderManager et AuthenticationProvider de base au lieu de tout implémenter. Je l'ai fait avec org.springframework.security.ldap.authentication.LdapAuthenticationProvider définissant un LdapAuthoritiesPopulator personnalisé, permettant de récupérer les rôles appropriés pour l'utilisateur.

J'espère que cette fois j'ai ce que vous cherchez. Bonne chance.

30
ezequielb

Je suis l'auteur de l'article en question.

Il existe sans doute de nombreuses façons de le faire, mais je le fais généralement en implémentant un UserDetails personnalisé qui connaît les rôles et les autorisations. Role et Permission ne sont que des classes personnalisées que vous écrivez. (Rien de spécial --Role a un nom et un ensemble de Permission instances, et Permission a un nom.) Ensuite, la getAuthorities() renvoie GrantedAuthority objets qui ressemblent à ceci:

PERM_CREATE_POST, PERM_UPDATE_POST, PERM_READ_POST

au lieu de retourner des choses comme

ROLE_USER, ROLE_MODERATOR

Les rôles sont toujours disponibles si votre implémentation UserDetails a une méthode getRoles(). (Je recommande d'en avoir un.)

Idéalement, vous attribuez des rôles à l'utilisateur et les autorisations associées sont automatiquement renseignées. Cela impliquerait d'avoir un UserDetailsService personnalisé qui sait comment effectuer ce mappage, et tout ce qu'il a à faire est de générer le mappage à partir de la base de données. (Voir l'article pour le schéma.)

Ensuite, vous pouvez définir vos règles d'autorisation en termes d'autorisations au lieu de rôles.

J'espère que ça t'as aidé.

76
Willie Wheeler

Les étapes de base sont les suivantes:

  1. Utiliser un fournisseur d'authentification personnalisé

    <bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton">
    ...
    </bean>
    
  2. Faites en sorte que votre fournisseur personnalisé retourne une implémentation personnalisée UserDetails. Ce UserDetailsImpl aura une getAuthorities() comme ceci:

    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>();
        for (GrantedAuthority role: roles) {
            permissions.addAll(getPermissionsIncludedInRole(role));
        }
        return permissions;
    }
    

Bien entendu, à partir de là, vous pouvez appliquer de nombreuses optimisations/personnalisations à vos besoins spécifiques.

6
gpeche

C'est le moyen le plus simple de le faire. Autorise les autorités de groupe, ainsi que les autorités d'utilisateur.

-- Postgres syntax

create table users (
  user_id serial primary key,
  enabled boolean not null default true,
  password text not null,
  username citext not null unique
);

create index on users (username);

create table groups (
  group_id serial primary key,
  name citext not null unique
);

create table authorities (
  authority_id serial primary key,
  authority citext not null unique
);

create table user_authorities (
  user_id int references users,
  authority_id int references authorities,
  primary key (user_id, authority_id)
);

create table group_users (
  group_id int references groups,
  user_id int referenecs users,
  primary key (group_id, user_id)
);

create table group_authorities (
  group_id int references groups,
  authority_id int references authorities,
  primary key (group_id, authority_id)
);

Puis dans META-INF/applicationContext-security.xml

<beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="passwordEncoder" />

<authentication-manager>
    <authentication-provider>

        <jdbc-user-service
                data-source-ref="dataSource"

                users-by-username-query="select username, password, enabled from users where username=?"

                authorities-by-username-query="select users.username, authorities.authority from users join user_authorities using(user_id) join authorities using(authority_id) where users.username=?"

                group-authorities-by-username-query="select groups.id, groups.name, authorities.authority from users join group_users using(user_id) join groups using(group_id) join group_authorities using(group_id) join authorities using(authority_id) where users.username=?"

                />

          <password-encoder ref="passwordEncoder" />

    </authentication-provider>
</authentication-manager>
5
Neil McGuigan

Juste pour être complet (peut-être que quelqu'un d'autre n'aura pas à l'implémenter à partir de zéro):

Nous avons mis en place notre propre petite bibliothèque, comme tout le monde. Il est censé faciliter les choses, afin que nos développeurs ne soient pas obligés de le réimplémenter à chaque fois. Ce serait formidable si la sécurité de printemps fournissait un support de rbac prêt à l'emploi, car cette approche est bien meilleure que celle basée sur les autorisations par défaut.

Regardez Github (OSS, MIT licence) pour voir si cela répond à vos besoins. En gros, il s’agit uniquement de mapper le mappage des privilèges de rôle. , vous devrez fournir vous-même le mappage des rôles <-> des utilisateurs, par exemple, en mappant des groupes (groupes racf/ad) vers des rôles (1: 1) ou en mettant en œuvre un mappage supplémentaire. , il n’a donc aucun sens de fournir une certaine implémentation.

Nous avons essentiellement utilisé cela en interne, afin de pouvoir commencer par rbac depuis le début. Nous pouvons toujours la remplacer ultérieurement par une autre implémentation, si l'application se développe, mais il est important pour nous que la configuration soit correcte dès le début.

Si vous n'utilisez pas rbac, il y a de fortes chances que les autorisations soient disséminées dans toute la base de code et vous aurez du mal à extraire/grouper celles-ci (dans des rôles) ultérieurement. Les graphiques générés aident également à raisonner à ce sujet/à le restructurer ultérieurement.

1
Alexander Pilch