Vai al contenuto principale

Introduzione

CSRF (Cross-Site Request Forgery) è un attacco che, impersonando un utente autenticato, gli fa inviare richieste non volute. Ad esempio, supponi che la tua applicazione abbia POST /user/email per accettare la modifica dell’indirizzo email. Se un attaccante prepara su un altro sito un form che invia automaticamente a questo URL, l’indirizzo email dell’utente potrebbe essere modificato a sua insaputa. In Laravel 13, grazie al meccanismo incluso nel gruppo di middleware web, la protezione CSRF è abilitata per impostazione predefinita.

Prevenzione degli attacchi CSRF

Il middleware PreventRequestForgery di Laravel previene il CSRF con due livelli.
  1. Verifica dell’Origin (header Sec-Fetch-Site)
  2. Verifica del token (token CSRF per sessione)
Prima controlla l’Origin e, se non è possibile determinarlo o la verifica fallisce, ricade sulla verifica del token.

Verifica dell’Origin

Laravel controlla inizialmente Sec-Fetch-Site per stabilire se la richiesta proviene dalla stessa Origin. È particolarmente efficace in ambiente HTTPS. Se la verifica dell’Origin ha successo, la richiesta è consentita in quel momento. In caso contrario, viene eseguita la verifica del token CSRF come in passato.
Sec-Fetch-Site è pensato per essere usato su connessioni HTTPS. In ambiente HTTP la verifica dell’Origin non funziona e la difesa principale è la verifica del token.

Modalità Origin-only

Puoi disabilitare il fallback sulla verifica del token e affidarti solo alla verifica dell’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);
    });
In modalità Origin-only, le richieste che falliscono la verifica dell’Origin restituiscono 403 anziché 419. Se vuoi consentire richieste same-site, ad esempio tra sottodomini, imposta allowSameSite.
$middleware->preventRequestForgery(allowSameSite: true);

Verifica del token

Laravel genera un token CSRF per ciascuna sessione. Puoi ottenerlo con csrf_token() o dalla sessione.
use Illuminate\Http\Request;

Route::get('/token', function (Request $request) {
    $tokenFromSession = $request->session()->token();
    $tokenFromHelper = csrf_token();
});
Quando crei form POST, PUT, PATCH o DELETE in route web, includi sempre @csrf.
<form method="POST" action="/profile">
    @csrf

    <!-- input hidden equivalente -->
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

Esclusione di URI

Per le richieste inviate da servizi esterni, come i webhook di Stripe, potresti dover escludere URI specifici dalla protezione 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/*',
        ]);
    });
Quando possibile, colloca le route dei webhook al di fuori del gruppo di middleware web e mantieni le configurazioni di esclusione al minimo.

Header X-CSRF-TOKEN

Laravel verifica non solo il _token del form ma anche l’header X-CSRF-TOKEN. Per prima cosa emetti il token in un tag meta.
<meta name="csrf-token" content="{{ csrf_token() }}">
Poi passa questo valore nell’header delle richieste AJAX.
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': document
            .querySelector('meta[name="csrf-token"]')
            .getAttribute('content'),
    },
});

Header X-XSRF-TOKEN

Laravel invia anche un cookie XSRF-TOKEN cifrato. Axios e Angular possono impostare automaticamente questo valore nell’header X-XSRF-TOKEN per le richieste same-Origin. Di conseguenza, in implementazioni SPA o AJAX ci sono casi in cui la protezione CSRF è attiva senza scrivere manualmente la configurazione degli header.

Considerazioni per le SPA

Quando usi Laravel come backend API per una SPA, ottieni prima il cookie CSRF e poi invia la richiesta di login.
await axios.get('/sanctum/csrf-cookie');
await axios.post('/login', {
    email: '[email protected]',
    password: 'password',
});
Per i dettagli fai riferimento a Sanctum.
Ultima modifica il 13 luglio 2026