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 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 et la charge de notre serveur.
Par défaut, Spring Security définit pour nous des valeurs d'en-tête de contrôle de cache spécifiques, 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 remplaçonsconfigure() 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 point de terminaison REST simple:
@GetMapping("/default/users/{name}")
public ResponseEntity getUserWithDefaultCaching(@PathVariable String name) {
return ResponseEntity.ok(new UserDto(name));
}
L'en-têtecache-control résultant ressemblera à ceci:
[cache-control: no-cache, no-store, max-age=0, must-revalidate]
Enfin, mettons en œuvre 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");
Cela signifie essentiellement qu'un navigateur ne mettra jamais cette réponse en cache.
Bien que cela puisse sembler inefficace, il y a en fait une bonne raison à ce comportement par défaut -If one user logs out and another one logs in, we don’t want them to be able to see the previous users resources. 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. Redéfinition du comportement de la mise en cache par défaut
Parfois, nous pouvons avoir affaire à des ressources que nous voulons mettre en cache. Si nous le permettons, il serait plus sûr de le faire ressource 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 méthode de gestionnaire unique, en utilisant le cacheCacheControl. La classeCacheControl est un constructeur 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));
}
Examinons 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 notre réponse sera désormais 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 les en-têtes de contrôle du 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éthodeconfigure desWebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().disable();
}
Maintenant, faisons une nouvelle 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 constater, aucun en-tête de cache n'a été défini. Encore une fois,this is not secure but proves how we can turn off the default headers if we want to.
7. Conclusion
Cet article montre comment Spring Security désactive la mise en cache HTTP par défaut et explique le fait 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 comme bon nous semble.
L'implémentation de tous ces exemples et extraits de code peut être trouvée dans leGitHub project - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.