Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐘
Intermediaire 25 min Laravel

Securiser une application Laravel

Pourquoi Securiser une application Laravel ?

L'application web est aujourd'hui un élément essentiel de notre vie quotidienne et professionnelle. La sécurité est donc un enjeu majeur pour tout développeur web, y compris ceux travaillant avec le framework Laravel. Un site ou une application non sécurisée peut être facilement piraté, ce qui entraîne la perte des données personnelles des utilisateurs, les pertes financières et même les dommages à la réputation de l'entreprise.

Un cas d'usage concret : Imaginez que vous développez un site e-commerce en Laravel. Si cette application n'est pas sécurisée, elle est vulnérable aux attaques telles que l'injection SQL, le piratage des comptes utilisateurs et la diffusion de données confidentielles.

Prerequis

  • Connaissance avancée du PHP
  • Familiarité avec les concepts d'architecture MVC (Model-View-Controller)
  • Maîtrise de Laravel (routes, controllers, views, migrations, etc.)
  • Connaissance des bases de données SQL et ORM Eloquent
  • Compréhension des mécanismes de sécurité HTTP (HTTPS, CSRF, XSS, etc.)

Outils à installer :

  • PHP 8.1 ou ultérieur
  • Composer (gère les dépendances du projet)
  • Node.js (pour les packages frontaux si nécessaire)
  • Laravel Installer (pour créer rapidement un nouveau projet)

Installation des outils :

## Installez PHP 8.1 via le gestionnaire de paquets de votre système
sudo apt update && sudo apt install php8.1

## Installez Composer
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer

## Installez Node.js (version recommandée pour Laravel)
sudo apt install nodejs npm

## Installez le Laravel Installer
composer global require laravel/installer

Concepts fondamentaux

1. Authentification et Authorization

L'authentification est le processus de vérifier l'identité d'un utilisateur, tandis que l'autorisation détermine les actions qu'il peut effectuer.

Schema mental :

  • Authentification : Utilisateur s'identifie
  • Authorization : Utilisateur fait une action spécifique

Code fonctionnel :

// Authentification avec Laravel Breeze
composer require laravel/breeze --dev
php artisan breeze:install

// Migration pour l'utilisateur
php artisan make:migration create_users_table --create=users

// Création du modèle User et de la migration correspondante
php artisan make:model User -m

// Migration de création des utilisateurs (dans db/migrations)
Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

2. Hashing des mots de passe

Les mots de passe doivent être stockés en toute sécurité dans la base de données. Laravel utilise le hashage pour ce faire.

Schema mental :

  • Hashing : Convertir un mot de passe en une chaîne sécurisée

Code fonctionnel :

// Utilisation du facade Hash
use Illuminate\Support\Facades\Hash;

$hashedPassword = Hash::make('my-secret-password');

if (Hash::check('my-secret-password', $hashedPassword)) {
    // Mot de passe correct
}

3. Middleware

Les middleware sont des fonctions qui s'exécutent avant ou après une requête HTTP. Ils sont utilisés pour effectuer des tâches comme l'authentification et la vérification des permissions.

Schema mental :

  • Middleware : Filtrage des requêtes HTTP

Code fonctionnel :

// Création d'un middleware personnalisé
php artisan make:middleware CheckAge

// Modification du middleware (app/Http/Middleware/CheckAge.php)
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAge
{
    public function handle(Request $request, Closure $next)
    {
        if ($request->age <= 18) {
            return redirect('home');
        }

        return $next($request);
    }
}

// Enregistrement du middleware dans app/Http/Kernel.php
protected $routeMiddleware = [
    // ...
    'check.age' => \App\Http\Middleware\CheckAge::class,
];

4. Validation des données

La validation des données est essentielle pour prévenir les injections SQL et les autres attaques.

Schema mental :

  • Validation : Vérification des entrées utilisateur

Code fonctionnel :

// Utilisation de la validation dans un controller
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'name' => 'required|max:255',
        'email' => 'required|email|unique:users',
        'age' => 'integer|min:18',
    ]);

    if ($validator->fails()) {
        return redirect('register')
                    ->withErrors($validator)
                    ->withInput();
    }

    // Validation réussie, continuez les opérations
}

Mise en pratique : projet fil rouge

Pour mettre en pratique ce que nous avons appris, construisons un gestionnaire de tâches simple. Ce projet comprendra :

  1. Authentification et autorisation des utilisateurs.
  2. Création, mise à jour et suppression de tâches.

Structure du projet :

task-manager/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── TaskController.php
│   │   ├── Middleware/
│   │   │   ├── AuthMiddleware.php
│   │   ├── Routes/web.php
│   ├── Models/
│   │   ├── Task.php
│   ├── Database/
│   │   ├── Migrations/2014_10_12_000000_create_tasks_table.php
├── resources/
│   ├── views/
│   │   ├── auth/
│   │   │   ├── login.blade.php
│   │   ├── tasks/
│   │   │   ├── index.blade.php
│   │   │   ├── create.blade.php
│   ├── js/app.js
├── routes/
│   └── web.php
├── storage/
├── tests/
├── .env.example
├── composer.json
└── package.json

Étapes du projet :

  1. Création du projet Laravel
laravel new task-manager --api
cd task-manager
  1. Installation des dépendances
composer require laravel/ui
php artisan ui vue --auth
npm install && npm run dev
  1. Configuration de la base de données
  • Modifiez .env pour configurer votre base de données.
  1. Création du modèle et de la migration
php artisan make:model Task -m
  1. Mise à jour de la migration
// database/migrations/2014_10_12_000000_create_tasks_table.php
Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('description')->nullable();
    $table->boolean('completed')->default(false);
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->timestamps();
});
  1. Exécution de la migration
php artisan migrate
  1. Création du contrôleur pour les tâches
php artisan make:controller TaskController --resource
  1. Ajout des routes
// routes/web.php
Route::get('/tasks', [TaskController::class, 'index']);
Route::get('/tasks/create', [TaskController::class, 'create']);
Route::post('/tasks', [TaskController::class, 'store']);
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit']);
Route::put('/tasks/{task}', [TaskController::class, 'update']);
Route::delete('/tasks/{task}', [TaskController::class, 'destroy']);
  1. Création des vues
  • resources/views/tasks/index.blade.php
  • resources/views/tasks/create.blade.php
  • resources/views/tasks/edit.blade.php
  1. Ajout des styles et scripts Modifiez resources/js/app.js pour ajouter du JavaScript personnalisé.

Code final :

// app/Models/Task.php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'description', 'completed'];
}

// app/Http/Controllers/TaskController.php
namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;

class TaskController extends Controller
{
    public function index()
    {
        return view('tasks.index', ['tasks' => auth()->user()->tasks]);
    }

    public function create()
    {
        return view('tasks.create');
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'description' => 'nullable',
        ]);

        Task::create($validatedData + ['user_id' => auth()->id()]);

        return redirect('/tasks');
    }

    public function edit(Task $task)
    {
        return view('tasks.edit', ['task' => $task]);
    }

    public function update(Request $request, Task $task)
    {
        $validatedData = $request->validate([
            'title' => 'required|max:255',
            'description' => 'nullable',
            'completed' => 'boolean',
        ]);

        $task->update($validatedData);

        return redirect('/tasks');
    }

    public function destroy(Task $task)
    {
        $task->delete();

        return redirect('/tasks');
    }
}

// resources/views/tasks/index.blade.php
@extends('layouts.app')

@section('content')
<h1>Tâches</h1>
<a href="/tasks/create">Ajouter une tâche</a>

<ul>
    @foreach ($tasks as $task)
    <li>
        $task->title
        <form action="/tasks/$task->id" method="POST">
            @csrf
            @method('DELETE')
            <button type="submit">Supprimer</button>
        </form>
    </li>
    @endforeach
</ul>
@endsection

// resources/views/tasks/create.blade.php
@extends('layouts.app')

@section('content')
<h1>Ajouter une tâche</h1>
<form action="/tasks" method="POST">
    @csrf
    <label for="title">Titre</label>
    <input type="text" name="title" id="title">

    <label for="description">Description</label>
    <textarea name="description" id="description"></textarea>

    <button type="submit">Ajouter</button>
</form>
@endsection

// resources/views/tasks/edit.blade.php
@extends('layouts.app')

@section('content')
<h1>Modifier une tâche</h1>
<form action="/tasks/$task->id" method="POST">
    @csrf
    @method('PUT')
    <label for="title">Titre</label>
    <input type="text" name="title" id="title" value="$task->title">

    <label for="description">Description</label>
    <textarea name="description" id="description">$task->description</textarea>

    <button type="submit">Modifier</button>
</form>
@endsection

Erreurs frequentes et debugging

1. Mauvaise validation des données

## ❌ Mauvais
public function store(Request $request)
{
    $task = new Task;
    $task->title = $request->input('title');
    $task->save();
}

## ✅ Correct
public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|max:255',
        'description' => 'nullable',
    ]);

    Task::create($validatedData);

    return redirect('/tasks');
}

2. Mauvaise gestion des erreurs d'authentification

## ❌ Mauvais
public function login(Request $request)
{
    if (Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')])) {
        return redirect('/dashboard');
    } else {
        return back()->withErrors([
            'email' => 'Identifiants incorrects',
        ]);
    }
}

## ✅ Correct
public function login(Request $request)
{
    if (Auth::attempt($request->only('email', 'password'))) {
        return redirect('/dashboard');
    }

    return back()->withErrors([
        'email' => 'Identifiants incorrects',
    ]);
}

3. Mauvaise gestion des erreurs de redirection

## ❌ Mauvais
public function store(Request $request)
{
    Task::create($request->all());

    return redirect('/tasks');
}

## ✅ Correct
public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|max:255',
        'description' => 'nullable',
    ]);

    Task::create($validatedData);

    return redirect()->route('tasks.index')->with('success', 'Tâche ajoutée avec succès');
}

Pour aller plus loin

  1. Authentification sociale : Utilisez Laravel Socialite pour ajouter des plateformes de connexion telles que Facebook, Google, etc.
  2. Cryptography : Utilisez Laravel's Crypt facade pour chiffrer et déchiffrer les données sensibles.
  3. API Security : Apprenez à sécuriser vos API avec OAuth et JWT.

Défi pratique : Ajoutez une fonctionnalité de filtrage des tâches par statut (complétées/non-complétées) dans l'application gestionnaire de tâches.

Besoin d'aide sur Laravel ?

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

Recevoir des conseils

Questions frequentes

Quelles sont les meilleures pratiques pour sécuriser une application Laravel ?
Il est recommandé d'utiliser le framework Laravel par défaut, qui intègre de nombreuses fonctionnalités de sécurité telles que la protection contre les injections SQL, les failles XSS et la protection CSRF. Il faut également utiliser des packages tiers comme Laravel Sanctum pour une authentification sécurisée et des règles de validation fortifiées pour les entrées utilisateur.
Comment protéger mes données sensibles dans un projet Laravel ?
Pour protéger vos données sensibles, utilisez le fichier .env pour stocker des informations comme les clés API et les mots de passe. Assurez-vous que ce fichier est inclus dans votre .gitignore afin qu'il ne soit pas publié sur le dépôt distant. Utilisez également des variables d'environnement chiffrées si vous devez gérer des données sensibles directement dans votre code.
Quels sont les dangers associés aux vulnérabilités de sécurité courantes dans Laravel ?
Les principales vulnérabilités dans Laravel incluent les injections SQL, les failles XSS et CSRF. Il est essentiel de suivre les bonnes pratiques telles que la validation et la normalisation des entrées utilisateur, l'utilisation de requêtes paramétrisées et le respect des politiques de sécurité CORS pour prévenir ces types de vulnérabilités.

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.