Added CSRF protection
This commit is contained in:
@@ -8,16 +8,24 @@ use Dotenv\Dotenv;
|
|||||||
use Slim\Factory\AppFactory;
|
use Slim\Factory\AppFactory;
|
||||||
use Slim\Views\TwigMiddleware;
|
use Slim\Views\TwigMiddleware;
|
||||||
use Slim\Views\Twig;
|
use Slim\Views\Twig;
|
||||||
|
use Slim\Csrf\Guard;
|
||||||
use Medoo\Medoo;
|
use Medoo\Medoo;
|
||||||
use App\Controllers\PostController;
|
use App\Controllers\PostController;
|
||||||
use App\Repositories\PostRepository;
|
use App\Repositories\PostRepository;
|
||||||
use App\Services\HtmlSanitizer;
|
use App\Services\HtmlSanitizer;
|
||||||
use App\Services\HtmlPurifierFactory;
|
use App\Services\HtmlPurifierFactory;
|
||||||
|
use App\Services\CsrfExtension;
|
||||||
use App\Database\Migrator;
|
use App\Database\Migrator;
|
||||||
use App\Bootstrap;
|
use App\Bootstrap;
|
||||||
use App\Routes;
|
use App\Routes;
|
||||||
use App\Config;
|
use App\Config;
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// Démarrer la session PHP
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Vérifier les répertoires
|
// Vérifier les répertoires
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -38,16 +46,29 @@ $dotenv->load();
|
|||||||
$env = $_ENV['APP_ENV'] ?? 'production';
|
$env = $_ENV['APP_ENV'] ?? 'production';
|
||||||
$isDev = strtolower($env) === 'development';
|
$isDev = strtolower($env) === 'development';
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// Initialisation de l'application Slim
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
$app = AppFactory::create();
|
||||||
|
$responseFactory = $app->getResponseFactory();
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Initialisation des services
|
// Initialisation des services
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
|
// CSRF Guard (middleware)
|
||||||
|
$csrf = new Guard($responseFactory);
|
||||||
|
|
||||||
// Twig
|
// Twig
|
||||||
$twig = Twig::create(
|
$twig = Twig::create(
|
||||||
__DIR__ . '/../views',
|
__DIR__ . '/../views',
|
||||||
['cache' => Config::getTwigCache($isDev)]
|
['cache' => Config::getTwigCache($isDev)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ajouter l'extension CSRF à Twig
|
||||||
|
$twig->addExtension(new CsrfExtension($csrf));
|
||||||
|
|
||||||
// Medoo (SQLite)
|
// Medoo (SQLite)
|
||||||
$dbFile = Config::getDatabasePath();
|
$dbFile = Config::getDatabasePath();
|
||||||
$db = new Medoo([
|
$db = new Medoo([
|
||||||
@@ -69,13 +90,15 @@ $htmlSanitizer = new HtmlSanitizer($htmlPurifier);
|
|||||||
$postRepository = new PostRepository($db);
|
$postRepository = new PostRepository($db);
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Slim App
|
// Middleware
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
$app = AppFactory::create();
|
|
||||||
$app->addBodyParsingMiddleware();
|
$app->addBodyParsingMiddleware();
|
||||||
$app->add(TwigMiddleware::create($app, $twig));
|
$app->add(TwigMiddleware::create($app, $twig));
|
||||||
|
|
||||||
|
// Enregistrer le middleware CSRF pour toutes les routes
|
||||||
|
$app->add($csrf);
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// Routes
|
// Routes
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
38
src/Services/CsrfExtension.php
Normal file
38
src/Services/CsrfExtension.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Slim\Csrf\Guard;
|
||||||
|
use Twig\Extension\AbstractExtension;
|
||||||
|
use Twig\Extension\GlobalsInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Twig pour accéder aux tokens CSRF dans les templates.
|
||||||
|
*/
|
||||||
|
final class CsrfExtension extends AbstractExtension implements GlobalsInterface
|
||||||
|
{
|
||||||
|
public function __construct(private Guard $csrf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGlobals(): array
|
||||||
|
{
|
||||||
|
$csrfNameKey = $this->csrf->getTokenNameKey();
|
||||||
|
$csrfValueKey = $this->csrf->getTokenValueKey();
|
||||||
|
$csrfName = $this->csrf->getTokenName();
|
||||||
|
$csrfValue = $this->csrf->getTokenValue();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'csrf' => [
|
||||||
|
'keys' => [
|
||||||
|
'name' => $csrfNameKey,
|
||||||
|
'value' => $csrfValueKey,
|
||||||
|
],
|
||||||
|
'name' => $csrfName,
|
||||||
|
'value' => $csrfValue,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,10 @@
|
|||||||
<a href="/admin/edit/{{ post.id }}" class="btn btn-sm btn-secondary">Éditer</a>
|
<a href="/admin/edit/{{ post.id }}" class="btn btn-sm btn-secondary">Éditer</a>
|
||||||
|
|
||||||
<form method="post" action="/admin/delete/{{ post.id }}" style="display:inline;">
|
<form method="post" action="/admin/delete/{{ post.id }}" style="display:inline;">
|
||||||
|
{# Tokens CSRF #}
|
||||||
|
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||||
|
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||||
|
|
||||||
<button type="submit" class="btn btn-sm btn-danger"
|
<button type="submit" class="btn btn-sm btn-danger"
|
||||||
onclick="return confirm('Supprimer cet article ?')">
|
onclick="return confirm('Supprimer cet article ?')">
|
||||||
Supprimer
|
Supprimer
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ Créer un article
|
|||||||
|
|
||||||
{# Formulaire identifié pour le script JavaScript #}
|
{# Formulaire identifié pour le script JavaScript #}
|
||||||
<form id="articleForm" method="post" action="{{ action }}">
|
<form id="articleForm" method="post" action="{{ action }}">
|
||||||
|
{# Tokens CSRF #}
|
||||||
|
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||||
|
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<label for="title">Titre<br>
|
<label for="title">Titre<br>
|
||||||
<input type="text" id="title" name="title" value="{{ post.title|default('') }}" required maxlength="255">
|
<input type="text" id="title" name="title" value="{{ post.title|default('') }}" required maxlength="255">
|
||||||
|
|||||||
Reference in New Issue
Block a user