Ce qui se passe
Le composant ExpressionLanguage fait tourner une bonne partie de Symfony : les attributs #[IsGranted] et
#[Cache], les règles access_control, les gardes de workflow. Symfony 8.2 le rend plus rapide, plus sûr et
signale les erreurs avant la production. Trois changements, tous annoncés par le blog officiel.
Des expressions compilées en PHP
Jusqu'ici, Symfony mettait les expressions analysées en cache, mais chaque évaluation devait encore les reconstruire depuis ce cache : 15 à 30 µs, autant que de les analyser de nouveau. Les gardes de workflow n'étaient pas mises en cache du tout.
En 8.2, toutes ces expressions sont compilées en PHP au réchauffement du cache. Évaluer revient à appeler une méthode statique : environ 1 µs, le coût d'une closure équivalente. Aucun changement n'est demandé à l'application, et la compilation est désactivée en mode debug, ce qui permet de modifier des fonctions d'expression sans vider le cache.
Des erreurs détectées avant la production
Une expression est une chaîne : une faute de frappe ne se voit qu'à l'évaluation. En 8.2 :
- le réchauffement du cache échoue si une règle
access_controlou une garde de workflow contient une expression invalide, y compris une variable ou une fonction inconnue ; - une commande
lint:expressionscontrôle ces expressions ainsi que celles des attributs de contrôleur#[IsGranted],#[IsCsrfTokenValid]et#[Cache]. Contrairement au réchauffement, elle fonctionne en mode debug, donc en intégration continue.
php bin/console lint:expressionsLimiter l'accès aux constantes
Une expression ne lit que les variables qu'on lui passe, sauf constant() et enum() : elles lisent n'importe
quelle constante ou case d'enum de l'application. Quand les expressions viennent d'utilisateurs, cela peut exposer
des valeurs sensibles comme des clés d'API.
Symfony 8.2 ajoute un ConstantFunctionProvider qui restreint les deux fonctions aux constantes autorisées.
L'étoile * remplace tout sauf ::. Les noms sont vérifiés avant la lecture, donc une classe hors liste n'est
jamais chargée par l'autoloader.
- Les versions sans restriction de
constant()etenum()sont dépréciées. - Les ExpressionLanguage créés par Symfony enregistrent déjà ce fournisseur ; pour les vôtres, enregistrez-le
vous-même, avec
['*', '*::*']pour tout autoriser.
Source : blog Symfony, de Nicolas Grekas. Source en anglais.