Ajoute la protection CSRF sur tous les formulaires et requêtes AJAX
Un jeton unique par session (core/csrf.py, exposé côté Jinja via csrf_token()) est vérifié sur toute requête non-GET par un before_request (core/csrf_guard.py), dans le même esprit que core/auth_guard.py : une seule garde globale plutôt que de toucher aux ~90 routes existantes une par une. L'app entière fait déjà transiter ses formulaires par fetch() : pjax.js intercepte chaque <form> interne et le transforme lui-même en requête fetch (aucun usage de l'attribut d'échappement data-no-pjax nulle part dans le repo, confirmé par grep). Il suffit donc de patcher window.fetch UNE SEULE FOIS (static/csrf_fetch.js) pour y ajouter automatiquement l'en-tête X-CSRFToken sur toute requête non-GET, formulaires pjax comme fetch() écrits à la main dans screen_edit.html/game_dashboard.html/ play.html — sans modifier un seul appel existant. La vérification est désactivée quand app.config["TESTING"] est actif (même convention que Flask-WTF/WTF_CSRF_ENABLED), pour ne pas avoir à ajouter le jeton aux ~170 tests existants qui appellent les routes directement via le client de test Flask. tests/test_csrf.py réactive volontairement la garde pour la mettre à l'épreuve pour de vrai (GET jamais bloqué, POST sans jeton/avec mauvais jeton -> 400, POST avec le bon jeton via l'en-tête ou le champ de formulaire -> succès). templates/play.html reçoit les mêmes deux balises que base.html car il est autonome (ne l'étend pas, propre <html>/<head>). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
989e899a96
commit
a52b244f27
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* csrf_fetch.js — pose automatiquement le jeton CSRF (voir core/csrf.py/
|
||||
* core/csrf_guard.py) sur CHAQUE fetch() non-GET de l'appli, sans avoir à
|
||||
* modifier individuellement les nombreux appels fetch() déjà écrits à la
|
||||
* main (screen_edit.html, game_dashboard.html, play.html...) ni les
|
||||
* formulaires classiques (pjax.js les transforme lui-même en fetch(), voir
|
||||
* son commentaire d'en-tête — cette rustine s'applique donc aussi à eux).
|
||||
*
|
||||
* window.CSRF_TOKEN est posé une fois par templates/base.html (valeur
|
||||
* injectée par Jinja, voir core/csrf.py::get_csrf_token) — chargé AVANT ce
|
||||
* script pour qu'il soit déjà disponible ici.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
if (window.fetch.__forgeCsrfPatched) return; // rejoué par pjax.js (runScriptsIn) sans effet une 2e fois
|
||||
var originalFetch = window.fetch;
|
||||
function patchedFetch(input, init) {
|
||||
init = init || {};
|
||||
var method = (init.method || "GET").toUpperCase();
|
||||
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
||||
var headers = new Headers(init.headers || {});
|
||||
if (!headers.has("X-CSRFToken") && window.CSRF_TOKEN) {
|
||||
headers.set("X-CSRFToken", window.CSRF_TOKEN);
|
||||
}
|
||||
init = Object.assign({}, init, { headers: headers });
|
||||
}
|
||||
return originalFetch(input, init);
|
||||
}
|
||||
patchedFetch.__forgeCsrfPatched = true;
|
||||
window.fetch = patchedFetch;
|
||||
})();
|
||||
Reference in New Issue
Block a user