Quantcast
Channel: Active questions tagged symfony4 - Stack Overflow
Viewing all articles
Browse latest Browse all 3921

Custom voter does not work as expected after migrating from Symfony 3.4 to Symfony 4.4

$
0
0

I'm migrating an app from Symfony 3.4 to Symfony 4.4. This app gives admin users the possibility to edit the role needed to access each route, so all the roles and routes are stored in the database.

To check if the user has access to a route, a voter is called on each request, and is configured in the services.yaml file.

In Symfony 3.4, the voter was called on each request, without adding any more code. In the web profiler, i can see the list of voters, and the decision from the AccessDecisionManager ("Granted" or "Denied").

Screenshot of the Web Profiler for Symfony 3.4

In Symfony 4.4 however, the voters don't seem to be called at all. In the web profiler, my custom voter is still in the list (two times ??), but there is no decision from the AccessDecisionManager.

Screenshot of the Web Profiler for Symfony 4.4

If I check user access directly from the controller by adding this line $this->denyAccessUnlessGranted("", $request);, the voters are called and work as expected.

If someone could explain to me why I have to call the denyAccessUnlessGranted() method manually in Symfony 4.4 when it was not needed in Symfony 3.4 ? Was I using voters the wrong way in 3.4 ?

Thank you.

My custom voter class :

namespace App\Security;use Doctrine\ORM\EntityManager;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Security\Core\User\UserInterface;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;class DynamicAccessVoter implements VoterInterface{    // Routes everyone has access to    const PUBLIC_ROUTES = ["login"    ];    // Routes everyone who's connected has access to    const PRIVATE_ROUTES = ["homepage","fos_js_routing","fos_js_routing_js"    ];    // Routes everyone has access to only in dev mode    const DEV_ROUTES = ["_wdt","_profiler","_profiler_home","_profiler_search","_profiler_search_bar","_profiler_phpinfo","_profiler_search_results","_profiler_open_file","_profiler_router","_profiler_exception","_profiler_exception_css","_twig_error_test"    ];    private $env;    /**     * Constructor     *      * @param string $env - App environment (dev or prod)     */    public function __construct(String $env = "") {        $this->env = $env;    }    /**     * Custom voter     *      * @param TokenInterface $token     * @param Request $subject     * @param array $env     */    public function vote($token, $subject, $attributes) {        // Verifie si $subject est une instance de Request        if(!$subject instanceof Request) {            return self::ACCESS_ABSTAIN;        }        $route = $subject->attributes->get("_route");        // Verifie si la route est une route publique (accessible par tout le monde)        if(in_array($route, DynamicAccessVoter::PUBLIC_ROUTES)) {            return self::ACCESS_GRANTED;        }        // Verifie si l'application est en développement et la route nécéssaire pour le debug        if($this->env == "dev" && in_array($route, DynamicAccessVoter::DEV_ROUTES)) {            return self::ACCESS_GRANTED;        }        // Verifie si $utilisateur est une instance de UserInterface        if(!$token->getUser() instanceof UserInterface) {            return self::ACCESS_ABSTAIN;        }        // Verifie si la route est une route accéssible par tout utilisateur connecté        if(in_array($route, DynamicAccessVoter::PRIVATE_ROUTES)) {            return self::ACCESS_GRANTED;        }        // Verifie si l'utilisateur connectéà le droit d'accéder à cette route        if($token->getUser()->hasAccessTo($route)) {            return self::ACCESS_GRANTED;        }        return self::ACCESS_DENIED;    }}

My custom voter configured as a service in the services.yaml file :

app.dynamic_access_voter:    class: App\Security\DynamicAccessVoter    arguments: ["%kernel.environment%"]    tags:        - { name: security.voter }

My security.yaml file, if that can help :

security:    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers    encoders:        App\Entity\Utilisateur:            algorithm: bcrypt    providers:        main:            entity:                class: App\Entity\Utilisateur                property: email          firewalls:        main:            anonymous: true            provider: main            pattern: ^/            form_login:                login_path: login                check_path: login                always_use_default_target_path: true                default_target_path: homepage            logout:                path: /logout                target: /login            user_checker: App\Security\EnabledUserChecker    access_control:        - { path: ^/ }

Viewing all articles
Browse latest Browse all 3921

Trending Articles