Un SecurityConfigurer de printemps personnalisé

Un configurateur de sécurité de printemps personnalisé

1. Vue d'ensemble

La prise en charge de la configuration Java de Spring Security nous fournit une puissante API permettant de définir des mappages de sécurité et des règles pour une application.

Dans cet article rapide, nous allons voir comment nous pouvons faire un pas en avant et définir réellement un configurateur personnalisé; this is an advanced and flexible way to introduce custom logic into a standard security configuration.

Pour notre exemple rapide ici, nous allons ajouter une fonctionnalité qui enregistre les erreurs pour les utilisateurs authentifiés en fonction d'une liste donnée de codes d'état d'erreur.

2. UnSecurityConfigurer personnalisé

Pour commencer à définir notre configurateur, tout d'abordwe need to extend the AbstractHttpConfigurer class:

public class ClientErrorLoggingConfigurer
  extends AbstractHttpConfigurer {

    private List errorCodes;

    // standard constructors

    @Override
    public void init(HttpSecurity http) throws Exception {
        // initialization code
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
       http.addFilterAfter(
         new ClientErrorLoggingFilter(errorCodes),
         FilterSecurityInterceptor.class);
    }
}

Ici,the main method we need to override is the configure() method - qui contient la configuration de sécurité à laquelle ce configurateur s'appliquera.

Dans notre exemple, nous avons enregistré un nouveau filtre après le dernier filtre Spring Security. De plus, étant donné que nous avons l'intention de consigner les codes d'erreur d'état des réponses, nous avons ajouté une propriétéerrorCodes List que nous pouvons utiliser pour contrôler les codes d'erreur que nous allons consigner.

Nous pouvons également éventuellement ajouter une configuration supplémentaire dans la méthodeinit(), qui est exécutée avant la méthodeconfigure().

Ensuite, définissons la classe de filtre Spring Security que nous enregistrons dans notre implémentation personnalisée:

public class ClientErrorLoggingFilter extends GenericFilterBean {

    private static final Logger logger = LogManager.getLogger(
      ClientErrorLoggingFilter.class);
    private List errorCodes;

    // standard constructor

    @Override
    public void doFilter(
      ServletRequest request,
      ServletResponse response,
      FilterChain chain)
      throws IOException, ServletException {
        //...

        chain.doFilter(request, response);
    }
}

Il s'agit d'une classe de filtre Spring standard qui étendGenericFilterBean et remplace la méthodedoFilter(). Il possède deux propriétés représentant l’enregistreur que nous utiliserons pour afficher les messages et lesList deerrorCodes.

Examinons de plus près la méthodedoFilter():

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null) {
    chain.doFilter(request, response);
    return;
}
int status = ((HttpServletResponse) response).getStatus();
if (status < 400 || status >= 500) {
    chain.doFilter(request, response);
    return;
}
if (errorCodes == null) {
    logger.debug("User " + auth.getName() + " encountered error " + status);
} else {
    if (errorCodes.stream().anyMatch(s -> s.value() == status)) {
        logger.debug("User " + auth.getName() + " encountered error " + status);
    }
}

Si le code d'état est un code d'état d'erreur client, c'est-à-dire entre 400 et 500, nous vérifierons la listeerrorCodes.

Si ce champ est vide, nous afficherons tout code d’état d’erreur du client. Sinon, nous vérifierons d'abord si le code d'erreur fait partie desList de codes d'état donnés.

3. Utilisation du configurateur personnalisé

Maintenant que nous avons notre API personnalisée,we can add it to the Spring Security configuration by defining the bean, then by using the apply() method deHttpSecurity:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
          //...
          .and()
          .apply(clientErrorLogging());
    }

    @Bean
    public ClientErrorLoggingConfigurer clientErrorLogging() {
        return new ClientErrorLoggingConfigurer() ;
    }
}

Nous pouvons également définir le bean avec une liste spécifique de codes d'erreur que nous voulons consigner:

@Bean
public ClientErrorLoggingConfigurer clientErrorLogging() {
    return new ClientErrorLoggingConfigurer(Arrays.asList(HttpStatus.NOT_FOUND)) ;
}

Et c'est tout! Maintenant, notre configuration de sécurité inclura le filtre personnalisé et affichera les messages du journal.

Si nous voulons que le configurateur personnalisé soit ajouté par défaut, nous pouvons utiliser le fichierMETA-INF/spring.factories:

org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = com.example.dsl.ClientErrorLoggingConfigurer

Et pour le désactiver manuellement, nous pouvons alors utiliser la méthodedisable():

//...
.apply(clientErrorLogging()).disable();

4. Conclusion

Dans ce rapide tutoriel, nous nous sommes concentrés sur une fonctionnalité avancée de la prise en charge de la configuration de Spring Security -we’ve seen how to define our own, custom SecurityConfigurer.

Comme toujours, le code source complet de l'exemple peut être trouvéover on GitHub.