Introduction aux expressions de sécurité de printemps

Introduction aux expressions de sécurité de printemps

1. introduction

Dans ce didacticiel, nous nous concentrerons sur les expressions de sécurité Spring, et bien sûr sur des exemples pratiques avec ces expressions.

Avant d’examiner des implémentations plus complexes (comme ACL), il est important de bien maîtriser les expressions de sécurité, car elles peuvent être assez flexibles et puissantes si elles sont utilisées correctement.

Cet article est une extension deSpring Security Expressions – hasRole Example.

2. Dépendances Maven

Pour utiliser Spring Security, vous devez inclure la section suivante dans votre fichierpom.xml:


    
        org.springframework.security
        spring-security-web
        4.1.1.RELEASE
    

La dernière version peut être trouvéehere.

Et une note rapide - cette dépendance ne couvre que Spring Security; n'oubliez pas d'ajouter spring-core etspring-context pour une application Web complète.

3. Configuration

Tout d'abord, examinons une configuration Java.

Nous allons étendreWebSecurityConfigurerAdapter - afin que nous ayons la possibilité de nous connecter à l'un des points d'extension proposés par la classe de base:

@Configuration
@EnableAutoConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
    ...
}

Nous pouvons bien sûr aussi faire une configuration XML:



    

4. Expressions de sécurité Web

Voyons maintenant les expressions de sécurité:

  • Hasrole, Hasanyrole

  • Hasauthority, Hasanyauthority

  • Permitall, Denyall

  • Isanonymous, Isrememberme, Isauthenticated, Isfullyauthenticated

  • Principal, authentification

  • hasPermission

Et passons maintenant à chacun de ces éléments en détail.

4.1. hasRole, hasAnyRole

Ces expressions sont responsables de la définition du contrôle d'accès ou de l'autorisation d'accès à des URL ou méthodes spécifiques dans votre application.

Regardons l'exemple:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasRole("ADMIN")
    .antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
    ...
}

Dans cet exemple, nous spécifions l'accès à tous les liens commençant par/auth/ restreints aux utilisateurs connectés avec le rôleUSER ou le rôleADMIN. De plus, pour accéder aux liens commençant par/auth/admin/ nous besoin d'avoir le rôle deADMINdans le système.

La même configuration peut être réalisée dans un fichier XML en écrivant:


    
    

4.2. hasAuthority, hasAnyAuthority

Les rôles et les autorités sont similaires au printemps.

La principale différence est que les rôles ont une sémantique spéciale - à partir de Spring Security 4, le préfixe «ROLE_» est automatiquement ajouté (s’il n’y est pas déjà) par toute méthode liée aux rôles.

Ainsi,hasAuthority(‘ROLE_ADMIN') est similaire àhasRole(‘ADMIN') car le préfixe «ROLE_» est ajouté automatiquement.

Mais la bonne chose à propos de l'utilisation des autorités est que nous n'avons pas du tout à utiliser le préfixeROLE_.

Voici un exemple rapide où nous définissons des utilisateurs dotés d'autorités spécifiques:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
      .withUser("user1").password("user1Pass")
      .authorities("USER")
      .and().withUser("admin").password("adminPass")
      .authorities("ADMIN");
}

Nous pouvons alors bien sûr utiliser ces expressions d'autorité:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasAuthority("ADMIN")
    .antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
    ...
}

Comme nous pouvons le voir, nous ne parlons pas du tout de rôles ici.

Enfin, nous pouvons bien sûr obtenir la même fonctionnalité en utilisant la configuration XML:


    
        
            
            
        
    

And:


    
    

4.3. permitAll, denyAll

Ces deux annotations sont également très simples. Nous pouvons soit autoriser l'accès à certaines URL de notre service, soit refuser l'accès.

Jetons un œil à l'exemple:

...
.antMatchers("/*").permitAll()
...

Avec cette configuration, nous autoriserons tous les utilisateurs (anonymes et connectés) à accéder à la page commençant par ‘/ '(notre page d’accueil, par exemple).

Nous pouvons également refuser l'accès à l'ensemble de notre espace URL:

...
.antMatchers("/*").denyAll()
...

Et encore une fois, la même configuration peut être faite avec une configuration XML:


     
     

4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated

Dans cette sous-section, nous nous concentrons sur les expressions liées au statut de connexion de l'utilisateur. Commençons par l'utilisateur qui ne s'est pas connecté à notre page. En spécifiant ce qui suit dans la configuration Java, nous permettons à tous les utilisateurs non autorisés d'accéder à notre page principale:

...
.antMatchers("/*").anonymous()
...

La même chose dans la configuration XML:


    

Si nous voulons sécuriser le site Web afin que tous ceux qui l'utilisent soient tenus de se connecter, nous devons utiliser la méthodeisAuthenticated():

...
.antMatchers("/*").authenticated()
...

ou version XML:


    

De plus, nous avons deux expressions supplémentaires,isRememberMe() etisFullyAuthenticated(). Grâce à l'utilisation de cookies, Spring permet aux fonctionnalités de mémorisation de moi-même, il n'est donc pas nécessaire de se connecter au système à chaque fois. Vous pouvez liremore about Remember Me here.

Afin de donner accès aux utilisateurs qui ont été connectés uniquement par la fonction Remember me, nous pouvons utiliser ceci:

...
.antMatchers("/*").rememberMe()
...

ou version XML:


    

Enfin, certaines parties de nos services nécessitent l’authentification de l’utilisateur même si celui-ci est déjà connecté. Par exemple, l'utilisateur souhaite modifier les paramètres ou les informations de paiement; il est bien entendu une bonne pratique de demander une authentification manuelle dans les zones les plus sensibles du système.

Pour ce faire, nous pouvons spécifierisFullyAuthenticated(), qui renvoietrue si l'utilisateur n'est pas un utilisateur anonyme ou se souvient-moi:

...
.antMatchers("/*").fullyAuthenticated()
...

ou la version XML:


    

4.5. principal, authentication

Ces expressions permettent d'accéder respectivement à l'objetprincipal représentant l'utilisateur autorisé (ou anonyme) actuel et l'objetAuthentication actuel à partir desSecurityContext.

Nous pouvons, par exemple, utiliserprincipal pour charger l’e-mail, l’avatar ou toute autre donnée d’un utilisateur accessible à l’utilisateur connecté.

Etauthentication fournit des informations sur l'objetAuthentication complet, ainsi que ses autorisations accordées.

Les deux sont décrits plus en détail dans l'article suivant:Retrieve User Information in Spring Security.

4.6. APIhasPermission

Cette expression estdocumented et est destinée à faire le pont entre le système d'expression et le système ACL de Spring Security, ce qui nous permet de spécifier des contraintes d'autorisation sur des objets de domaine individuels, basées sur des autorisations abstraites.

Voyons un exemple. Nous avons un service qui permet aux articles d'écriture coopérative, avec un éditeur principal, de décider quel article proposé par d'autres auteurs doit être publié.

Afin de permettre l'utilisation d'un tel service, nous pouvons créer les méthodes suivantes avec des méthodes de contrôle d'accès:

@PreAuthorize("hasPermission(#articleId, 'isEditor')")
public void acceptArticle(Article article) {
   …
}

Seul l'utilisateur autorisé peut appeler cette méthode, et l'utilisateur doit également avoir l'autorisationisEditor dans le service.

Nous devons également nous rappeler de configurer explicitement unPermissionEvaluator dans notre contexte d'application:


    



    

customInterfaceImplementation sera la classe qui implémentePermissionEvaluator.

Bien entendu, nous pouvons également le faire avec la configuration Java:

@Override
protected MethodSecurityExpressionHandler expressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler =
      new DefaultMethodSecurityExpressionHandler();
    expressionHandler.setPermissionEvaluator(new CustomInterfaceImplementation());
    return expressionHandler;
}

5. Conclusion

Ce didacticiel est une introduction complète et un guide des expressions de sécurité Spring.

Tous les exemples discutés ici sont disponibleson the GitHub project.