Gestion des CORS sur Laravel via un Middleware
La sécurité est un aspect crucial du développement web moderne, particulièrement lorsqu'il s'agit de gérer les requêtes cross-origin (CORS). Dans cet article, nous allons explorer comment implémenter une solution robuste de gestion des CORS sur Laravel à l'aide d'un middleware personnalisé.
Qu'est-ce que les CORS ?
Les CORS (Cross-Origin Resource Sharing) sont un mécanisme qui permet à un serveur web d'indiquer les origines autorisées à accéder à ses ressources. Cette sécurité est essentielle pour protéger vos applications contre les accès non autorisés.
Implémentation du Middleware
Notre solution s'articule autour de deux fichiers principaux : le Kernel.php
et un middleware personnalisé ContentSecurityPolicy.php
.
1. Configuration du Kernel
Dans le fichier Kernel.php
, nous déclarons notre middleware dans le groupe 'web' :
protected $middlewareGroups = [
'web' => [
// Autres middlewares...
\App\Http\Middleware\ContentSecurityPolicy::class,
],
];
2. Le Middleware ContentSecurityPolicy
Le middleware ContentSecurityPolicy
est le cœur de notre solution. Il définit les politiques de sécurité et les en-têtes CORS nécessaires.
Créez un fichier “ContentSecurityPolicy.php” dans votre dossier Middleware :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
class ContentSecurityPolicy
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
// Content Security Policy (CSP)
$cspDirectives = [
"default-src" => "'self'",
"script-src" => "'self' 'unsafe-inline' 'unsafe-eval'",
"style-src" => "'self' 'unsafe-inline'",
"img-src" => "'self' data: https:",
"font-src" => "'self' data:",
"connect-src" => "'self'",
"media-src" => "'self'",
"object-src" => "'none'",
"frame-src" => "'self'",
"frame-ancestors" => "'self'",
"base-uri" => "'self'",
"form-action" => "'self'",
"upgrade-insecure-requests" => null
];
$cspHeader = implode('; ', array_map(
function ($key, $value) {
return $value === null ? $key : "$key $value";
},
array_keys($cspDirectives),
$cspDirectives
));
// Set security headers
$response->headers->set('Content-Security-Policy', $cspHeader);
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
// Set Permissions-Policy header with commonly restricted features
$response->headers->set('Permissions-Policy',
'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()'
);
$response->headers->remove('X-Powered-By');
$response->headers->remove('server');
return $response;
}
}
Dans notre exemple, nous autorisons le script-src à “unsafe-eval” pour AlpineJS. Si vous souhaitez tout de fois être plus stricte et ne pas l’inclure, vous pouvez vous rendre ici pour une version d’AlpineJS plus stricte en matière d’eval: https://alpinejs.dev/advanced/csp
Bien entendu, ajoutez les domaines autorisés pour chacun des cas de votre application. Si vous souhaitez par exemple ajouter une iframe openstreetmap, modifiez vos CSP comme cela:
// Content Security Policy (CSP)
$cspDirectives = [
// autres directives ...
"frame-src" => "'self' https://www.openstreetmap.org/",
];