Passer au contenu principal

Créer des voters personnalisés en Symfony

Les Voters sont un outil puissant de Symfony qui permet de centraliser toute la logique d’autorisation, facilitant ainsi sa réutilisation à travers différentes parties de votre application.

Comment créer un Voter personnalisé en Symfony ?

Un Voter personnalisé comprend deux méthodes principales :

  • Voter::supports : Cette méthode est appelée pour vérifier si le Voter est applicable à l’attribut et au sujet donnés. Si cette méthode retourne true, alors la méthode voteOnAttribute() sera appelée.

  • Voter::voteOnAttribute : Cette méthode contient la logique d’autorisation. Elle doit retourner true pour autoriser l’accès et false pour le refuser.

Stratégies de décision d’accès avec les Voters Symfony

Symfony propose plusieurs stratégies de décision d’accès :

Affirmative (par défaut) Cette stratégie accorde l’accès dès qu’un Voter accorde l’accès.
Consensus Cette stratégie accorde l’accès s’il y a plus de Voters accordant l’accès que refusant. En cas d’égalité, la décision est basée sur l’option de configuration allow_if_equal_granted_denied (par défaut sur true).
Unanimous Cette stratégie n’accorde l’accès que si aucun Voter ne refuse l’accès.
Priority Cette stratégie accorde ou refuse l’accès au premier Voter qui ne s’abstient pas, en fonction de sa priorité de service.

Comment utiliser les Voters en Symfony ?

Symfony offre plusieurs façons d’utiliser les Voters pour restreindre l’accès :

  • Par rôles : Vous pouvez restreindre l’accès à certains rôles en utilisant l’annotation @IsGranted(). Par exemple : #[IsGranted('ROLE_ADMIN')].

  • Par Voter personnalisé : Vous pouvez également utiliser un Voter personnalisé avec l’annotation @IsGranted(). Par exemple : #[IsGranted('POST_SHOW', subject: 'post')].

L’annotation @Security offre une flexibilité supplémentaire par rapport à @IsGranted. Elle permet de transmettre une expression qui peut contenir une logique personnalisée. Par exemple : #[Security("is_granted('ROLE_ADMIN') and is_granted('POST_SHOW', post)")].