Voter non reconnu

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J'aurais besoin d'un œil extérieur.

Dans l'idée de mettre en place des sécurités d'accès sur certains objets, j'ai donc créé un voter. L'idée de base est de pouvoir choisir les rôles qui auront accès à l'objet lors de la création ou de l'édition de celui-ci.

Le hic, c'est que c'est comme si mon voter n'existait pas, en cela que je ne passe apparemment pas ni dans la méthode supports(…), ni dans voteOnAttribute(…), alors que le service est bien instancié.

Est-ce que quelqu'un pourrait me dire qu'est-ce qui cloche ?

Merci d'avance  :)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
namespace My\WonderfulBundle\Security;

use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use My\WonderfulBundle\Entity\Access;

class AccessVoter extends Voter
{
    private $decisionManager;

    public function __construct(AccessDecisionManagerInterface $decisionManager)
    {
        $this->decisionManager = $decisionManager;
    }

    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        if ($this->decisionManager->decide($token, $subject->getRoles())) {
            return true;
        }
    }

    protected function supports($attribute, $subject)
    {
        // only vote on Access objects inside this voter
        if (!$subject instanceof Access) {
            return false;
        }

        return true;
    }
}

+0 -0

Tu peux nous donner la configuration, histoire qu'on vérifie ensemble ?

Elle doit ressembler à ça:

1
2
3
4
5
6
7
services:
    app.access_voter:
        class: My\WonderfullBundle\Security\AccessVoter
        arguments: ['@security.access.decision_manager']
        public: false
        tags:
            - { name: security.voter }

Tu as bien mis arguments ?

+1 -0

J'ai bien mis arguments avec le même service, je n'ai peut-être juste pas mis que le service n'était pas public, mais j'imagine que c'est un détail (je n'ai plus le code sous la main en ce moment).

Vu que la classe est instanciée, on est OK de ce côté-là.

+0 -0

Je n'ai pas l'impression de voir quelque chose de faux ni dans ton voteur, ni dans la conf. Du coup j'ai une autre question, comment l'invoques-tu ? via isGranted/denyAccessUnlessGranted, ou is_granted dans un Template ? Comment es-tu sûr que la classe est instanciée mais que la méthode support n'est pas appelée ? (Tiens d'ailleurs, ça me fait me demander, Est-ce qu'il y a mieux pour débugger ce genre de trucs que de faire du die à l'ancienne ?)

+0 -0

Je souhaite utiliser isGranted('unAttributAuHasardParceQuIlEnFautUnApparemment', $lObjetAccess) dans mon contrôleur, l'idée étant de jeter une 403 à l'accès en édition et/ou à l'affichage.
En fait, je finis par me demander s'il ne manque pas une autre partie de configuration ou que simplement mon appel avec un attribut bidon ne fait pas tout foirer, parce que si j'active les lignes qui font cette vérification, je n'ai plus possibilité de visualiser ou d'éditer les détails de n'importe-quel objet, j'ai une 403 qui sort, même si je suis censé avoir les droits.
Autre élément parce que je ne peux pas trop demander sans tout fournir : les rôles enregistrés dans l'objet sont vides par défaut, je devrais peut-être mettre au moins IS_AUTHENTICATED_FULLY, je rajouterai cet élément "par défaut" demain.

Pour savoir que la classe est bien instanciée et les deux méthodes pas appelées, j'utilise xdebug et je fais une exécution pas à pas dans Eclipse, avec des points d'arrêt dans les méthodes que j'aimerais voir appelées. Le script s'arrête donc bien dans le constructeur, mais ne passe jamais dans les deux méthodes, les deux points d'arrêt n'étant jamais rencontrés.

+0 -0

En fait, je finis par me demander s'il ne manque pas une autre partie de configuration ou que simplement mon appel avec un attribut bidon ne fait pas tout foirer, parce que si j'active les lignes qui font cette vérification, je n'ai plus possibilité de visualiser ou d'éditer les détails de n'importe-quel objet, j'ai une 403 qui sort, même si je suis censé avoir les droits.

Pour la configuration, perso dans mon projet j'ai deux voteurs qui sont configurés comme ceci et ça marche :

1
2
3
4
5
    app.XXXAccessChecker:
        class: AppBundle\Controller\XXXAccessChecker
        arguments: ['@security.access.decision_manager', '@doctrine']
        public: false
        tags: [{ name: security.voter }]

Donc si tu as quelque chose de similaire ça devrait fonctionner.

Si le constructeur est appelé, ça veut dire que ton service est en tout cas bien référencé. Par contre si en appelant denyAccessUnlessGranted il te jette une 403 sans même appeler ta méthode support, ça me fait penser qu'il ne reconnaît peut-être pas ton service comme étant un voteur. Le tag est-il présent et correct ?

Autre possibilité, effectivement, l'attribut. Mais si tu n'en as pas besoin, que tu ne le vérifies pas, et que tu as mis n'importe quelle string non vide, je ne vois pas pourquoi ça ne fontionnerait pas; ou du moins pas pourquoi la méthode support ne serait pas appelée. Juste, ne pas oublier que, aussi bien pour isGranted que denyAccessUnlessGranted ou is_granted en twig, le premier argument est l'attribut, et le second l'objet. Je ne sais pas si on a le droit de passer autre chose qu'une string en tant qu'attribut, je n'ai jamais vu aucun exemple passant autre chose en tout cas; d'où peut-être un if pas string alors dehors direct, sans même boucler sur les instances de voteurs pour voir s'il y en a un qui correspond au cas demandé.

Autre élément parce que je ne peux pas trop demander sans tout fournir : les rôles enregistrés dans l'objet sont vides par défaut, je devrais peut-être mettre au moins IS_AUTHENTICATED_FULLY, je rajouterai cet élément "par défaut" demain.

Ca c'est un risque que tu te fasses jeter par la méthode voteONAttribute. Mais avant de faire ça il faudrait d'abord savoir pourquoi support n'est pas appelé avant. La méthode support doit nécessairement être appelée avant voteOnAttribute, parce qu'avant de savoir si ton voteur donne l'accès ou non, Symfony doit d'abord savoir si c'est bien ce voteur-là qui est responsable pour ce couple attribut/objet et pas un autre.

D'où ma conclusion pour l'instant, ton service est instancié mais pas reconnu comme étant un voteur pour je ne sais quelle raison, peut-être une erreur de configuration effectivement.

+1 -0

:-°

Je me disais bien que c'était très probablement une stupidité : le tag n'était pas bon, reste d'un copié-collé… >_<

Heureusement que j'ai eu tout le week-end pour celle-là  ^^

Merci à tous !

(topic solved man !)

Nek

J'attends d'avoir testé avant, au cas où je pourrai le recycler, mais ce ne sera pas nécessaire, apparemment.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte