Principali vulnerabilità e best practices per proteggere le tue API REST.
La sicurezza delle API REST e' spesso sottovalutata durante lo sviluppo, ma diventa critica in produzione. Una API non sicura espone i tuoi utenti, i loro dati e la tua infrastruttura a rischi concreti.
Non usare sessioni per le API. Il pattern corretto e' Access Token breve + Refresh Token lungo:
Con Laravel Sanctum:
$accessToken = $user->createToken(
'access',
['*'],
now()->addMinutes(15)
)->plainTextToken;
$refreshToken = $user->createToken(
'refresh',
['refresh'],
now()->addDays(30)
)->plainTextToken;
Il rate limiting previene brute force e abusi:
// Endpoint pubblici - 60 req/min
Route::middleware(['throttle:60,1'])->group(function () {
Route::get('/products', [ProductController::class, 'index']);
});
// Endpoint sensibili - 5 req/min
Route::middleware(['throttle:5,1'])->group(function () {
Route::post('/auth/login', [AuthController::class, 'login']);
Route::post('/auth/forgot-password', [AuthController::class, 'forgot']);
});
Non fidarti mai dell'input dell'utente, anche se autenticato:
class CreateProductRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'price' => 'required|numeric|min:0|max:99999.99',
'category_id' => 'required|integer|exists:categories,id',
'description' => 'nullable|string|max:5000',
'tags' => 'nullable|array|max:10',
];
}
}
Configura sempre i seguenti header nelle risposte API:
return $response
->header('X-Content-Type-Options', 'nosniff')
->header('X-Frame-Options', 'DENY')
->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
->header('Referrer-Policy', 'strict-origin-when-cross-origin');
Un CORS troppo permissivo vanifica qualsiasi misura di sicurezza:
// config/cors.php
return [
'paths' => ['api/*'],
'allowed_origins' => [
'https://app.tuodominio.com',
],
'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'],
'allowed_headers' => ['Content-Type', 'Authorization'],
];
Usa UUID o ULID negli endpoint pubblici invece di ID numerici incrementali. Gli ID sequenziali permettono a un attaccante di enumerare tutte le risorse.
// Evita: GET /api/users/1, /api/users/2, /api/users/3
// Preferisci: GET /api/users/01HX7K9M2N3P4Q5R6S7T8V9W0
Registra tentativi di login falliti, accessi a risorse non autorizzate e anomalie:
Log::warning('Login fallito', [
'email' => $request->email,
'ip' => $request->ip(),
'ua' => $request->userAgent(),
]);
/api/v1/ per poter fare breaking changes in futuroLa sicurezza non e' una feature da aggiungere alla fine, ma una pratica da seguire dall'inizio. Implementa questi principi fin dalla prima riga di codice e mantieni le dipendenze sempre aggiornate.
Un'API sicura non e' solo buona tecnica: e' una responsabilita' verso i tuoi utenti.