Spring Security - En-têtes de contrôle du cache

1. Introduction

Dans cet article, nous allons explorer comment nous pouvons contrôler la mise en cache HTTP avec Spring Security.

Nous démontrerons son comportement par défaut et expliquerons également le raisonnement qui le sous-tend. Nous examinerons ensuite les moyens de modifier ce comportement, partiellement ou complètement.

2. Comportement de mise en cache par défaut

En utilisant efficacement les en-têtes de contrôle du cache, nous pouvons demander à notre navigateur de mettre en cache les ressources et d'éviter les sauts de réseau. Cela diminue la latence, ainsi que la charge sur notre serveur.

Par défaut, Spring Security définit des valeurs d'en-tête de contrôle de cache spécifiques pour nous, sans que nous ayons à configurer quoi que ce soit.

Tout d'abord, configurons Spring Security pour notre application:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception {} }

Nous surchargons configure () pour ne rien faire, cela signifie que nous n'avons pas besoin d'être authentifiés pour atteindre un point de terminaison, ce qui nous permet de nous concentrer uniquement sur le test de la mise en cache.

Ensuite, implémentons un simple point de terminaison REST:

@GetMapping("/default/users/{name}") public ResponseEntity getUserWithDefaultCaching(@PathVariable String name) { return ResponseEntity.ok(new UserDto(name)); }

L'en - tête de contrôle de cache résultant ressemblera à ceci:

[cache-control: no-cache, no-store, max-age=0, must-revalidate]

Enfin, implémentons un test qui atteint le point de terminaison et affirmons quels en-têtes sont envoyés dans la réponse:

given() .when() .get(getBaseUrl() + "/default/users/Michael") .then() .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") .header("Pragma", "no-cache");

Essentiellement, cela signifie qu'un navigateur ne mettra jamais en cache cette réponse.

Bien que cela puisse sembler inefficace, il existe en fait une bonne raison à ce comportement par défaut - Si un utilisateur se déconnecte et qu'un autre se connecte, nous ne voulons pas qu'il puisse voir les ressources des utilisateurs précédents . Il est beaucoup plus sûr de ne rien mettre en cache par défaut et de nous laisser la responsabilité d'activer explicitement la mise en cache.

3. Remplacement du comportement de mise en cache par défaut

Parfois, nous pouvons avoir affaire à des ressources que nous voulons mettre en cache. Si nous voulons l'activer, il serait plus sûr de le faire par ressource. Cela signifie que toutes les autres ressources ne seront toujours pas mises en cache par défaut.

Pour ce faire, essayons de remplacer les en-têtes de contrôle du cache dans une seule méthode de gestionnaire, en utilisant le cache CacheControl . La classe CacheControl est un générateur fluide, ce qui nous permet de créer facilement différents types de mise en cache:

@GetMapping("/users/{name}") public ResponseEntity getUser(@PathVariable String name) { return ResponseEntity.ok() .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS)) .body(new UserDto(name)); }

Frappons ce point de terminaison dans notre test et affirmons que nous avons changé les en-têtes:

given() .when() .get(getBaseUrl() + "/users/Michael") .then() .header("Cache-Control", "max-age=60");

Comme nous pouvons le voir, nous avons remplacé les valeurs par défaut, et maintenant notre réponse sera mise en cache par un navigateur pendant 60 secondes.

4. Désactivation du comportement de mise en cache par défaut

Nous pouvons également désactiver complètement les en-têtes de contrôle de cache par défaut de Spring Security. C'est une chose assez risquée à faire et pas vraiment recommandée. Mais, si nous le voulons vraiment, nous pouvons l'essayer en remplaçant la méthode configure de WebSecurityConfigurerAdapter:

@Override protected void configure(HttpSecurity http) throws Exception { http.headers().disable(); }

Maintenant, faisons à nouveau une demande à notre point de terminaison et voyons quelle réponse nous obtenons:

given() .when() .get(getBaseUrl() + "/default/users/Michael") .then() .headers(new HashMap());

Comme nous pouvons le voir, aucun en-tête de cache n'a été défini du tout. Encore une fois, ce n'est pas sécurisé mais prouve comment nous pouvons désactiver les en-têtes par défaut si nous le voulons.

5. Conclusion

Cet article montre comment Spring Security désactive la mise en cache HTTP par défaut et explique que c'est parce que nous ne voulons pas mettre en cache des ressources sécurisées. Nous avons également vu comment nous pouvons désactiver ou modifier ce comportement à notre guise.

L'implémentation de tous ces exemples et extraits de code se trouve dans le projet GitHub - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.