Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🔐
Intermediaire 25 min Spring Boot

Authentification dans Spring Boot

Authentification dans Spring Boot : Tutoriel Intermédiaire (25 min)

Pourquoi Authentification dans Spring Boot ?

L'authentification est un élément fondamental de toute application web ou d'API moderne, permettant à l'utilisateur de prouver son identité avant d'accéder aux ressources protégées. Dans le monde professionnel, une application sans authentification peut être facilement piratée, conduisant à des dommages financiers et réputationnels importants.

Un cas d'usage concret :Imaginez que vous développez un blog privé où les utilisateurs peuvent poster des articles. Vous ne voulez pas que tout le monde puisse écrire sur votre blog sans autorisation. L'authentification est donc essentielle pour protéger cette ressource et assurer que seuls les membres autorisés peuvent publier.

Prerequis

Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :

  • Connaissance de base de Java et Spring Boot
  • Une IDE comme IntelliJ IDEA ou Eclipse
  • Maven installé (version 3.5+)
  • Un navigateur web pour tester l'application
  • Un compte GitHub (facultatif) pour cloner le code

Concepts fondamentaux

1. Authentification vs Authorization

Authentification : Cette étape vérifie qui est l'utilisateur en utilisant des informations d'identification comme un nom d'utilisateur et un mot de passe.

Authorization : Après une authentification réussie, cette étape détermine quelles actions ou ressources sont disponibles pour l'utilisateur authentifié.

// Authentification
public boolean authenticate(String username, String password) {
    // Code pour vérifier les informations d'identification
}

// Authorization
public boolean isAuthorized(User user, String action) {
    // Code pour déterminer si l'utilisateur a le droit de l'action
}

2. Spring Security

Spring Security est une bibliothèque Java qui fournit des fonctionnalités d'authentification et d'autorisation robustes.

// Ajouter la dépendance dans pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

3. UserDetails et UserDetailsService

UserDetails : Cette interface représente un utilisateur authentifié.

UserDetailsService : Cette interface permet de récupérer des détails d'utilisateur.

// Implémentation de UserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // Code pour charger les détails de l'utilisateur
    }
}

4. AuthenticationManager

L'AuthenticationManager est responsable de la gestion des requêtes d'authentification.

// Configuration de AuthenticationManager
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
    return authConfig.getAuthenticationManager();
}

Mise en pratique : Projet fil rouge

Nous allons créer un mini-projet simple qui permet à l'utilisateur de s'inscrire, se connecter et accéder à une ressource protégée.

Étape 1 : Création du projet Spring Boot

Créer un nouveau projet Spring Boot via Spring Initializr.

  • Project : Maven Project
  • Language : Java
  • Spring Boot : La dernière version stable
  • Project Metadata
    • Group : fr.example
    • Artifact : auth-springboot-demo
    • Name : auth-springboot-demo
    • Description : Authentification Spring Boot Demo
    • Package name : fr.example.authspringbootdemo
  • Packaging : Jar
  • Java : 11 ou plus récent
  • Dependencies :
    • Spring Web
    • Spring Security

Étape 2 : Configuration de la sécurité

Créer un fichier SecurityConfig.java pour configurer la sécurité.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/api/public/**").permitAll() // Ressources publiques
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Étape 3 : Création des controllers

Créer un controller pour les routes publiques et protégées.

@RestController
@RequestMapping("/api")
public class AuthController {

    @GetMapping("/public/hello")
    public String helloPublic() {
        return "Hello, Public User!";
    }

    @GetMapping("/protected/hello")
    @PreAuthorize("hasRole('USER')")
    public String helloProtected() {
        return "Hello, Protected User!";
    }
}

Étape 4 : Création des services

Créer un service pour gérer les utilisateurs.

@Service
public class UserService {

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // Implémentation de chargement d'utilisateur
    }

    public User save(User user) {
        // Implémentation de sauvegarde d'utilisateur
    }
}

Étape 5 : Création des entités et repositories

Créer une entité User et un repository pour persister les utilisateurs.

@Entity
public class User extends UserDetailsImpl implements Serializable {
    // Attributs, getters et setters
}

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

Étape 6 : Création de la classe d'entrée

Créer une classe UserDetailsImpl pour implémenter UserDetails.

public class UserDetailsImpl implements UserDetails {

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // Implémentation des rôles
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

Étape 7 : Création de l'interface d'utilisateur

Créer une interface utilisateur pour afficher le formulaire de connexion.

@Controller
public class LoginController {

    @GetMapping("/login")
    public String showLoginForm() {
        return "login";
    }

    @PostMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password) {
        // Implémentation de la connexion
    }
}

Étape 8 : Création des vues

Créer les fichiers HTML pour les vues (ex: login.html).

<!-- login.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form th:action="@{/login}" method="post">
        <input type="text" name="username" placeholder="Username" required />
        <input type="password" name="password" placeholder="Password" required />
        <button type="submit">Login</button>
    </form>
</body>
</html>

Étape 9 : Configuration de la base de données

Configurer une base de données (ex: H2) dans application.properties.

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true

Étape 10 : Exécution de l'application

Exécuter l'application via votre IDE ou en utilisant la commande Maven.

mvn spring-boot:run

Erreurs fréquentes et debugging

Erreur 1 : BadCredentialsException

Message d'erreur : org.springframework.security.authentication.BadCredentialsException: Bad credentials

Code incorrect :

@Autowired
private AuthenticationManager authenticationManager;

public void authenticate(String username, String password) {
    UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(username, password);
    authenticationManager.authenticate(authReq);
}

Code correct :

@Autowired
private AuthenticationManager authenticationManager;

public boolean authenticate(String username, String password) {
    UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(username, password);
    try {
        authenticationManager.authenticate(authReq);
        return true;
    } catch (BadCredentialsException e) {
        return false;
    }
}

Erreur 2 : AccessDeniedException

Message d'erreur : org.springframework.security.access.AccessDeniedException: Access is denied

Code incorrect :

@GetMapping("/protected/hello")
@PreAuthorize("hasRole('ADMIN')")
public String helloProtected() {
    return "Hello, Protected User!";
}

Code correct :

@GetMapping("/protected/hello")
@PreAuthorize("hasRole('USER')")
public String helloProtected() {
    return "Hello, Protected User!";
}

Erreur 3 : NullPointerException

Message d'erreur : java.lang.NullPointerException

Code incorrect :

@Autowired
private UserRepository userRepository;

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username).orElse(null);
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), AuthorityUtils.createAuthorityList("USER"));
}

Code correct :

@Autowired
private UserRepository userRepository;

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), AuthorityUtils.createAuthorityList("USER"));
}

Pour aller plus loin

  1. Intégration avec OAuth2 : Apprendre comment intégrer OAuth2 pour une authentification externe (Google, Facebook).

  2. Token-based authentication : Utiliser des tokens JWT pour la gestion de l'authentification.

  3. Custom authentication provider : Créer un fournisseur d'authentification personnalisé pour intégrer avec une base de données tierce ou un service externe.

Défi pratique

Défi : Ajouter une fonctionnalité d'inscription utilisateur pour votre application. Les utilisateurs devraient pouvoir s'inscrire en fournissant un nom d'utilisateur, un mot de passe et une adresse e-mail.

Besoin d'aide sur Spring Boot ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Quelle est l'importance de l'authentification dans une application Spring Boot ?
L'authentification est cruciale pour assurer la sécurité de votre application en vérifiant l'identité des utilisateurs avant leur accès aux ressources protégées.
Comment configurer l'authentification basée sur les utilisateurs locaux dans un projet Spring Boot ?
Pour configurer l'authentification basée sur les utilisateurs locaux, vous pouvez utiliser la classe `UserDetailsService` et créer une implémentation qui retourne des objets `UserDetails`. Ensuite, configurez Spring Security pour utiliser ce service.
Quelle est la différence entre l'authentification et l'autorisation dans Spring Boot ?
L'authentification vérifie l'identité de l'utilisateur (qui est-ce qui est connecté), tandis que l'autorisation détermine les actions que cet utilisateur peut effectuer sur les ressources de l'application.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.