Commençons par configurer la chaîne de filtres de sécurité de Spring Security pour l’authentification et l’autorisation.
Suivez moi dans la démonstration suivante :
Démarrez par le formulaire Spring Security par défaut, en utilisant la méthode formLogin(Customizer.withDefaults())
.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.formLogin(Customizer.withDefaults()).build();
}
Ajoutez des rôles d’utilisateur et d'administrateur à votre chaîne de filtres
Spring Security fournit des filtres qui peuvent être utilisés pour authentifier différents types de rôles. Définissez les deux rôles suivants dans votre application Spring Boot :
Utilisateur.
Administrateur.
Une fois qu'ils sont authentifiés, Spring Security se charge d’octroyer les autorisations appropriées, et contrôle l’accès aux données selon les rôles.
En premier lieu, ajoutez la méthode authorizeHttpRequests()
pour définir les rôles.
Ensuite, ajoutez la méthode requestMatchers()
pour définir l'association des rôles USER
(utilisateur) et ADMIN
(administrateur) avec des pages.
Cela permettra d’assurer l’étape d'autorisation pour les pages qui sont à la disposition des utilisateurs. Le rôle ADMIN
se voit attribuer une page d’accueil spécifique, /admin
, mais a également accès à /user
. Les utilisateurs ont accès à la page d’accueil /user
, mais ne devraient pas avoir accès à la page d’accueil /admin
. Ajoutez anyRequest().authenticated()
pour vous permettre d’utiliser le formulaire ci-dessous pour l’authentification.
Procédez comme suit, en ajoutant l’extrait de code à votre méthode filterChain()
qui gère les requêtes HTTP.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(auth -> {
auth.requestMatchers("/admin").hasRole("ADMIN");
auth.requestMatchers("/user").hasRole("USER");
auth.anyRequest().authenticated();
}).formLogin(Customizer.withDefaults()).build();
}
Votre chaîne de filtres de sécurité est programmée avec HTTPSecurity.
Maintenant, nous pouvons créer une chaîne de filtres de sécurité pour l'étape d’authentification de ce petit chef-d'œuvre.
Ajoutez des utilisateurs en mémoire
Sans utilisateur, notre chaîne de filtres de sécurité ne nous permettra pas d’aller bien loin. Pour commencer voyons comment ajouter des utilisateurs avec des rôles.
Ces utilisateurs seront définis en mémoire, bien que dans des projets de production cette méthode est à proscrire au bénéfice d’utilisateurs stockées par exemple dans une base de données.
Il faut ajouter une nouvelle méthode qui renverra une implémentation de l’interface UserDetailsService. Dans le monde de Spring Security, l’objet UserDetails permet de modéliser un utilisateur. L’objet UserDetailsService permet d’accéder à des utilisateurs.
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("user"))
.roles("USER").build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin"))
.roles("USER", "ADMIN").build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Je vous ai préparé un utilisateur et un admin avec lesquels vous pouvez vous connecter. Voici les identifiants :
USER role : utilisateur : user ; mot de passe : user.
ADMIN role : utilisateur : admin ; mot de passe : admin.
J’ai également ajouté un encodage aux mots de passe. Ainsi, même si j’ai écrit en dur des mots de passe simples, la méthode encode()
permet comme son nom l’indique de les encoder.
Pour mener à bien cet encodage, la méthode passwordEncoder()
a été rajoutée. Elle renvoie une instance de BCryptEncoder.
BCrypt est l’un des algorithmes d’encodage les plus reconnus en ce qui concerne les mots de passe. Je vous le recommande.
Révisez votre chaîne de filtres de sécurité
Révisons le fichier SpringSecurityconfig.java que vous venez de compléter. Il devrait ressembler à ça :
package com.openclassrooms.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(auth -> {
auth.requestMatchers("/admin").hasRole("ADMIN");
auth.requestMatchers("/user").hasRole("USER");
auth.anyRequest().authenticated();
}).formLogin(Customizer.withDefaults()).build();
}
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("user"))
.roles("USER").build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin"))
.roles("USER", "ADMIN").build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Mettez en place votre Contrôleur
Maintenant, il est temps de mettre en place votre contrôleur. Ce contrôleur va gérer l’affichage des pages une fois que nous serons authentifiés.
Nous allons créer deux pages :
une pour l’utilisateur ;
et une autre pour l’administrateur.
Dans cette démonstration nous avons suivi les étapes suivantes :
Faites un clic droit sur votre package com.openclassrooms -> New -> Package.
Pour le nom du package, ajoutez le mot controllers à votre nom de package principal. Le mien s’intitule com.openclassrooms.controllers.
Puis, faites un clic droit sur le package que vous venez de réaliser, com.openclassrooms.controller -> New -> Class.
Intitulez votre classe contrôleur LoginController.java.
Ajoutez l’annotation
@RestController
pour la prise en compte de votre classe en tant que contrôleur REST par Spring.
Ensuite, créez une méthode différente pour chaque rôle et utilisez l’annotation @GetMapping pour associer l’URL.
package com.openclassrooms.controllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@GetMapping("/user")
public String getUser() {
return "Welcome, User";
}
@GetMapping("/admin")
public String getAdmin() {
return "Welcome, Admin";
}
}
Maintenant, voyons ce que ça donne dans le navigateur.
Mettez en place votre Serveur Web
Lorsque vous lancez votre application, un serveur web Tomcat est démarré. Aucune configuration n’est nécessaire ; tout s’effectue automatiquement à la compilation et à l'exécution du code.
Plusieurs façons permettent de démarrer l’application. Dans mon cas, j’utilise le goal Maven : spring-boot:run.
Une fois le démarrage complété, vous pouvez ouvrir votre application web sur votre navigateur.
Ouvrez votre navigateur favori et tapez cette URL : http://localhost:8080/user
Maintenant, connectez-vous en tant que user et voyez ce qu’il se passe.
Yes, ça fonctionne ! Déconnectez vous avec la page http://localhost:8080/logout puis essayez l’utilisateur “admin”.
Voici quelques tests à mener pour être certain que vous l’avez correctement mis en place :
Que se passe-t-il lorsque vous rentrez le mauvais mot de passe ?
Que se passe-t-il lorsque vous tentez de consulter la page /admin alors que vous êtes connecté en tant que user ?
En résumé
Vous avez fait du beau travail, vous savez maintenant :
Créer des filtres avec authorizeHttpRequests() et requestMatchers() pour appliquer le contrôle d’accès basé sur des rôles à différentes URL.
Configurer le rôle des utilisateurs en utilisant une implémentation de UserDetailsService
Mettre en place les méthodes permettant de créer des pages d'accueil dynamiques pour les utilisateurs, en ayant recours à l’annotation GetMapping .
On dirait que votre page d’authentification Spring Security est prête.
Dans le prochain chapitre apprenez à configurez une authentification basée sur des utilisateurs en base de données.