Passer au contenu principal

Introduction

CSRF (Cross-Site Request Forgery) est une attaque qui consiste à envoyer des requêtes non voulues en usurpant l’identité d’un utilisateur connecté. Par exemple, supposons que votre application accepte un changement d’adresse e-mail via POST /user/email. Si un attaquant place sur un autre site un formulaire qui envoie automatiquement cette requête, l’adresse e-mail de l’utilisateur pourrait être modifiée sans qu’il s’en aperçoive. Dans Laravel 13, la protection CSRF est activée par défaut grâce au mécanisme inclus dans le groupe de middlewares web.

Prévention des attaques CSRF

Le middleware PreventRequestForgery de Laravel bloque les CSRF sur deux couches :
  1. Vérification de l’Origin (en-tête Sec-Fetch-Site)
  2. Vérification du token (token CSRF par session)
Laravel vérifie d’abord l’Origin, puis, si le contrôle n’est pas concluant ou échoue, il se rabat sur la vérification du token.

Vérification de l’Origin

Laravel commence par consulter Sec-Fetch-Site pour déterminer si la requête provient de la même Origin. C’est particulièrement efficace en HTTPS. Si la vérification de l’Origin réussit, la requête est autorisée à ce stade. Sinon, la vérification classique du token CSRF s’exécute.
Sec-Fetch-Site suppose une connexion HTTPS. En HTTP, la vérification de l’Origin ne fonctionne pas et la vérification du token reste la principale défense.

Mode Origin-only

Vous pouvez désactiver le repli sur la vérification du token pour ne juger la requête que par l’Origin.
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->preventRequestForgery(originOnly: true);
    });
En mode Origin-only, une requête dont la vérification de l’Origin échoue renvoie 403 au lieu de 419. Pour autoriser les requêtes same-site (entre sous-domaines par exemple), utilisez allowSameSite.
$middleware->preventRequestForgery(allowSameSite: true);

Vérification du token

Laravel génère un token CSRF par session. Vous pouvez l’obtenir avec csrf_token() ou depuis la session.
use Illuminate\Http\Request;

Route::get('/token', function (Request $request) {
    $tokenFromSession = $request->session()->token();
    $tokenFromHelper = csrf_token();
});
Lorsque vous créez des formulaires POST, PUT, PATCH ou DELETE sur des routes web, incluez toujours @csrf.
<form method="POST" action="/profile">
    @csrf

    <!-- Équivalent en input caché -->
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

Exclusion d’URI

Pour les requêtes venant de services externes (par exemple les webhooks Stripe), il peut être nécessaire d’exclure certaines URI de la protection CSRF.
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->preventRequestForgery(except: [
            'stripe/*',
            'http://example.com/foo/bar',
            'http://example.com/foo/*',
        ]);
    });
Dans la mesure du possible, placez les routes de webhook en dehors du groupe de middlewares web et gardez les exclusions au minimum.

En-tête X-CSRF-TOKEN

Laravel vérifie non seulement le _token du formulaire mais aussi l’en-tête X-CSRF-TOKEN. Exposez d’abord le token dans une balise meta.
<meta name="csrf-token" content="{{ csrf_token() }}">
Puis ajoutez cette valeur à l’en-tête de vos requêtes AJAX.
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': document
            .querySelector('meta[name="csrf-token"]')
            .getAttribute('content'),
    },
});

En-tête X-XSRF-TOKEN

Laravel envoie également un cookie chiffré XSRF-TOKEN. Axios et Angular peuvent utiliser cette valeur automatiquement dans l’en-tête X-XSRF-TOKEN pour les requêtes de même Origin. C’est pourquoi, dans une SPA ou une implémentation AJAX, la protection CSRF est parfois active sans que vous ayez à configurer l’en-tête manuellement.

Considérations pour les SPA

Lorsque vous utilisez Laravel comme backend d’API pour une SPA, récupérez d’abord le cookie CSRF avant d’envoyer la requête de connexion.
await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', {
    email: '[email protected]',
    password: 'password',
});
Consultez Sanctum pour plus de détails.
Dernière modification le 13 juillet 2026