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

Securiser une application Spring Boot

Pourquoi Securiser une application Spring Boot ?

La sécurité est un aspect crucial pour n'importe quelle application, mais en particulier dans les applications web modernes qui traitent des données sensibles ou des informations personnelles. En tant qu'application Spring Boot, il est essentiel de mettre en place des mesures de sécurité robustes pour protéger contre les menaces potentielles.

Un cas d'utilisation concret serait un système de gestion de contenu (CMS) où des utilisateurs peuvent publier et modifier des articles. Si ce système n'est pas sécurisé, il pourrait être facilement exploité par un attaquant pour publier du contenu malveillant ou même accéder aux informations sensibles.

Prerequis

  • Connaissance de base de Java
  • Familiarité avec Spring Boot
  • Connaissance des concepts fondamentaux d'authentification et d'autorisation
  • Installation de Java 11 ou plus tard
  • Installation de Maven
  • IDE (IntelliJ IDEA, Eclipse)

Concepts fondamentaux

Authentification vs Autorisation

Authentification : L'authentification est le processus par lequel un utilisateur prouve son identité. Elle vérifie que l'utilisateur qui se connecte est bien celui qu'il affirme être.

// Exemple de configuration d'un filter pour l'authentification avec Spring Security
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeRequests(authorize -> authorize
            .antMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated()
        )
        .httpBasic(Customizer.withDefaults());
    return http.build();
}

Autorisation : L'autorisation est le processus par lequel une fois l'utilisateur authentifié, on détermine les actions qu'il peut effectuer. Cela peut être basé sur des rôles (admin, user) ou des permissions spécifiques.

// Exemple de configuration d'un role-based authorization
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeRequests(authorize -> authorize
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

Utilisation de Spring Security

Spring Security est un framework populaire pour la gestion de la sécurité dans les applications Spring. Il fournit des outils pour l'authentification et l'autorisation, ainsi que des fonctionnalités comme le changement de mot de passe, la récupération d'account, etc.

// Exemple de configuration de Spring Security avec un UserDetailsService
@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.withDefaultPasswordEncoder()
        .username("user")
        .password("password")
        .roles("USER")
        .build();
    return new InMemoryUserDetailsManager(user);
}

Mise en pratique : projet fil rouge

Création du Projet

  1. Créer un nouveau projet Spring Boot

    • Utiliser le générateur de projets Spring Initializr (https://start.spring.io/)
    • Sélectionner Maven Project, Java 11, et ajouter les dépendances suivantes :
      • Spring Web
      • Spring Security
      • H2 Database
  2. Structure du Projet

    src/main/java/com/example/demo/
        ├── DemoApplication.java
        ├── controller/
        │   └── TaskController.java
        ├── model/
        │   └── Task.java
        ├── repository/
        │   └── TaskRepository.java
        └── service/
            └── TaskService.java
    
  3. Code Complet

// DemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
java
// Task.java
package com.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Task {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String description;
    private boolean completed;

    // Getters and Setters
}
java
// TaskRepository.java
package com.example.demo.repository;

import com.example.demo.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskRepository extends JpaRepository<Task, Long> {
}
java
// TaskService.java
package com.example.demo.service;

import com.example.demo.model.Task;
import com.example.demo.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TaskService {
    @Autowired
    private TaskRepository taskRepository;

    public Iterable<Task> findAll() {
        return taskRepository.findAll();
    }

    public Task save(Task task) {
        return taskRepository.save(task);
    }
}
java
// TaskController.java
package com.example.demo.controller;

import com.example.demo.model.Task;
import com.example.demo.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/tasks")
public class TaskController {
    @Autowired
    private TaskService taskService;

    @GetMapping
    public Iterable<Task> findAll() {
        return taskService.findAll();
    }

    @PostMapping
    public Task save(@RequestBody Task task) {
        return taskService.save(task);
    }
}
  1. Configuration de Security
// SecurityConfig.java
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorize -> authorize
                .antMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }
}
  1. Commandes à Executer
mvn clean install
java -jar target/demo-0.0.1-SNAPSHOT.jar

Erreurs frequentes et debugging

Erreur 403 Forbidden

Message d'erreur :

Forbidden
Access is denied.

Code Incorrect :

// Code incorrect qui cause une erreur 403
http.authorizeRequests(authorize -> authorize
    .anyRequest().permitAll()
);

Code Correct :

// Code correct pour autoriser toutes les requêtes publiques
http.authorizeRequests(authorize -> authorize
    .antMatchers("/api/public/**").permitAll()
    .anyRequest().authenticated()
);

Erreur 401 Unauthorized

Message d'erreur :

Unauthorized
Full authentication is required to access this resource.

Code Incorrect :

// Code incorrect qui cause une erreur 401
http.authorizeRequests(authorize -> authorize
    .anyRequest().authenticated()
);

Code Correct :

// Code correct pour authentifier les requêtes
http.authorizeRequests(authorize -> authorize
    .antMatchers("/api/public/**").permitAll()
    .anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());

Pour aller plus loin

  1. Utiliser des Tokens JWT

    • Ajouter une authentification stateless avec des tokens JSON Web Token (JWT).
  2. Implementer des Rôles et Permissions Avancés

    • Utiliser la bibliothèque Spring Security avec les rôles et permissions complexes.
  3. Gestion des Sessions

    • Configurer la gestion des sessions pour une meilleure sécurité.

Défi Pratique

Défi : Créer une application Spring Boot qui utilise un service d'authentification externe comme OAuth2 pour gérer l'authentification et l'autorisation.

Besoin d'aide sur Spring Boot ?

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

Recevoir des conseils

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.