L’un des quatre algorithmes de combinaison lit une chose que les trois autres ignorent : le poids qu’un votant met derrière sa réponse. C’est la plus petite fonctionnalité du composant, et la plus facile à détourner.
Chaque résultat porte un poids, et il vaut 1 par défaut.
AccessOutcome::deny('The account is suspended.', weight: 10);
Ce que majority en fait
Il additionne les poids des autorisations face aux poids des refus, et le côté le plus lourd l’emporte. Les abstentions restent hors des deux sommes, et hors du décompte des votants qui se sont exprimés.
Deux cas limites sont tranchés par configuration plutôt que par convention :
- Les deux côtés pèsent pareil, et au moins un votant s’est exprimé. La réponse vient d’
allow_if_equal_granted_denied, qui accorde par défaut. - Tous les votants se sont abstenus. Ce n’est pas une égalité, et c’est
allow_if_all_abstainqui décide à la place. Personne n’a rien dit, ce qui est un fait différent de deux camps qui disent le contraire avec la même force.
Ce défaut d’accorder en cas d’égalité n’est pas une affaire de goût. Il existe parce que le test de parité avec Symfony Security a trouvé la divergence : consensus accorde quand les deux côtés sont à égalité, une version antérieure de majority refusait, et les deux piles répondaient différemment à la même question. Les noms diffèrent exprès ; les réponses ne doivent pas.
Compter et peser
Le consensus de Security compte les votes là où celui-ci les pèse. Avec tous les poids laissés à leur défaut de 1, les deux s’accordent exactement, ce qui en fait un renommage sans risque pour une application qui migre et ne touche jamais à un poids.
XACML ne définit aucun algorithme de combinaison de ce genre. Celui-ci est une idée de Symfony, conservée parce que des applications s’appuient dessus, et dotée du nom qui décrit ce qu’il fait.
Ce qu’un poids n’est pas
Un poids permet de donner à un votant plus de voix que les autres sans lui donner de veto. C’est là tout son objet, et cela vaut d’être redit en forme d’avertissement : sous les trois autres algorithmes, le poids est simplement ignoré.
Ne comptez donc pas sur un gros poids pour rendre un votant décisif. Un votant de poids 1000 sous permit_overrides est un votant de poids 1, et le code se lit comme si une règle s’appliquait alors qu’il n’y en a aucune. Quand vous voulez qu’un votant ait le dernier mot, dites-le avec quelque chose qui le signifie :
deny_overrides, si le dernier mot est un refus que rien ne peut outrepasser.first_applicableet l’ordre des votants, si le dernier mot revient à qui parle le premier.
Ces deux-là sont visibles dans la configuration et dans le profileur. Un poids n’est visible qu’à l’intérieur du votant qui le porte, ce qui est exactement le mauvais endroit pour une règle qui concerne les autres.
Là où il justifie sa place
Un usage raisonnable est le signal de risque parmi des pairs : trois votants regardent la propriété, l’état du document et la réputation du demandeur, et le troisième vaut deux des autres sans pouvoir fermer la porte à lui seul.
Écrivez le poids à côté de la raison, dans le même appel, et le profileur montrera les deux. Tout ce qui est plus élaboré est un algorithme de combinaison à vous, que le composant rend peu coûteux à écrire.