Spring Security Custom AuthenticationFailureHandler

Authentification personnalisée Spring Security Custom

1. Vue d'ensemble

Dans ce tutoriel rapide, nous allons illustrer comment personnaliser la gestion des échecs d'authentification de Spring Security dans une application Spring Boot. L'objectif est d'authentifier les utilisateurs en utilisant une approcheform login.

Pour une introduction àSpring Security etForm Login inSpring Boot, veuillez vous référer respectivement à l'articlethis etthis.

2. Authentification et autorisation

Authentication etAuthorization sont souvent utilisés en conjonction car ils jouent un rôle essentiel, et tout aussi important, lorsqu'il s'agit d'accorder l'accès au système.

Cependant, ils ont des significations différentes et appliquent des contraintes différentes lors de la validation d'une requête:

  • Authentication - précèdeAuthorization; il s'agit de valider les informations d'identification reçues; c'est là que nous vérifions que le nom d'utilisateur et le mot de passe correspondent à ceux que notre application reconnaît

  • Authorization’occupe de vérifier si l’utilisateur authentifié avec succès dispose des autorisations nécessaires pour accéder à certaines fonctionnalités de l’application

Nous pouvons personnaliser la gestion des échecs deauthentication etauthorization, cependant, dans cette application, nous allons nous concentrer sur les échecs d'authentification.

3. AuthenticationFailureHandler de Spring Security

Spring Security fournit un composant qui gère les échecs d'authentification pour nous par défaut.

Cependant, il n’est pas rare de se retrouver dans un scénario où le comportement par défaut n’est pas suffisant pour répondre aux exigences.

Si tel est le cas, nous pouvons créer notre propre composant et fournir le comportement personnalisé souhaité en implémentant l'interfaceAuthenticationFailureHandler:

public class CustomAuthenticationFailureHandler
  implements AuthenticationFailureHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(
      HttpServletRequest request,
      HttpServletResponse response,
      AuthenticationException exception)
      throws IOException, ServletException {

        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        Map data = new HashMap<>();
        data.put(
          "timestamp",
          Calendar.getInstance().getTime());
        data.put(
          "exception",
          exception.getMessage());

        response.getOutputStream()
          .println(objectMapper.writeValueAsString(data));
    }
}

Par défaut,Springredirectsrenvoie l'utilisateur à la page de connexion avec unrequest parameter contenant des informations sur l'erreur.

Dans cette application, nous renvoyons une réponse 401 contenant des informations sur l'erreur, ainsi que l'horodatage de son occurrence.

Outre le composant par défaut,Spring a d'autres composants prêts à l'emploi que nous pouvons exploiter en fonction de ce que nous voulons faire:

  • DelegatingAuthenticationFailureHandler délègue les sous-classes deAuthenticationException à différentsAuthenticationFailureHandlers, ce qui signifie que nous pouvons créer différents comportements pour différentes instances deAuthenticationException

  • ExceptionMappingAuthenticationFailureHandler redirige l'utilisateur vers une URL spécifique en fonction du nom de classeAuthenticationException’s full

  • ForwardAuthenticationFailureHandler redirigera l'utilisateur vers l'URL spécifiée quel que soit le type desAuthenticationException

  • SimpleUrlAuthenticationFailureHandler est le composant qui est utilisé par défaut, il redirigera l'utilisateur vers unfailureUrl, if spécifié; sinon, il renverra simplement une réponse 401

Maintenant que nous avons créé nosAuthenticationFailureHandler personnalisés, configurons notre application et remplaçons le gestionnaire par défaut deSpring’s:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration
  extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
      throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("example")
          .password("example")
          .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http)
      throws Exception {
        http
          .authorizeRequests()
          .anyRequest()
          .authenticated()
          .and()
          .formLogin()
          .failureHandler(customAuthenticationFailureHandler());
    }

    @Bean
    public AuthenticationFailureHandler customAuthenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }
}

Notez le scallfailureHandler(), c'est là que nous pouvons dire àSpring d'utiliser notre composant personnalisé au lieu d'utiliser celui par défaut.

4. Conclusion

Dans cet exemple, nous avons personnalisé le gestionnaire d’échecs d’authentification de notre application en utilisant l’interfaceSpring’s AuthenticationFailureHandler.

L'implémentation de cet exemple peut être trouvée dansthe Github project.

Lors de l'exécution locale, vous pouvez accéder et tester l'application àlocalhost:8080