【问题标题】:getRoles() ignored in Symfony2在 Symfony2 中忽略 getRoles()
【发布时间】:2014-11-28 09:08:26
【问题描述】:

我的安全 yml 如下

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_USER:        ROLE_MEMBER
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:
                path:   /logout
                target: /
                invalidate_session: false
            anonymous:    true

    access_control:
        - { path: ^/login$,     role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register,   role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting,  role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/profile,    role: ROLE_MEMBER }
        - { path: ^/admin,      role: ROLE_ADMIN }
        - { path: ^/group,      role: ROLE_ADMIN }

我只是添加了一个名为 ROLE_MEMBER 的新角色,并只允许它访问配置文件路由。

如果配置文件设置为ROLE_USER,那么这工作正常。

我正在使用 FOSUserBundle,我有一个 fos_group 和 fos_user_group 表。下面以连接表为例。

我已成功使用此表为用户分配成员组,该组的角色只是ROLE_MEMBER

在控制器中使用以下代码,我可以看到用户具有ROLE_MEMBERROLE_USER 的角色。

$user  = $this->getUser();
$user->getRoles();

返回;

array(2) { [0]=> string(11) "ROLE_MEMBER" [1]=> string(9) "ROLE_USER" } 

我认为这是正确的。然而,该配置文件无法访问。如果我将配置文件更改为需要ROLE_USER,那么它可以工作并且可以访问。有趣的是,使用 Symfony 的调试部分,我可以看到实际上我的用户没有成员角色。

我是否遗漏了一个步骤来告诉 Symfony 我已分配给我的用户的角色,确保 getRoles() 返回正确的数组似乎无法按预期工作。

【问题讨论】:

    标签: security symfony acl fosuserbundle roles


    【解决方案1】:

    确实,根据您自己的回答,您必须重新验证您的用户。 如果你不想,你只需要告诉 symfony2 检查会话变量是否与数据库中的相同。

    为此,您必须为您的User 类实现EquatableInterface

    然后,实现以下方法:

    public function isEqualTo(UserInterface $user) {
        if ($user instanceof User) {
            // Check that the roles are the same, in any order
            $isEqual = count($this->getRoles()) == count($user->getRoles());
            if ($isEqual) {
                foreach($this->getRoles() as $role) {
                    $isEqual = $isEqual && in_array($role, $user->getRoles());
                }
            }
            return $isEqual;
        }
    
        return false;
    }
    

    如果此函数返回false,它将刷新身份验证上下文中的角色。

    来自文档How to Create a custom User Provider (The Symfony CookBook)

    Symfony 还使用用户名、salt 和密码来验证 用户在请求之间没有改变。未能序列化这些可能 导致您退出每个请求。如果您的用户实施 EquatableInterface,然后不是检查这些属性, 你的 isEqualTo 方法被简单地调用了,你可以检查任何 你想要的属性。除非你明白这一点,否则你可能不会 需要实现这个接口还是操心。

    【讨论】:

    • 什么时候调用?
    • 每个请求都会调用它。有关详细信息,请参阅编辑后的答案。
    • 我不认为这对我有用。因为我在注册控制器中注册后立即更改角色。所以在控制器结束和我期望角色发生变化的地方之间没有新的请求。
    • 我认为会的,因为每次提交表单(包括注册表单)后应该有一个重定向。重定向在客户端,以第二个请求结束。
    【解决方案2】:

    改变

    role_hierarchy:
        ROLE_USER:        ROLE_MEMBER
    

    role_hierarchy:
        ROLE_MEMBER:      ROLE_USER
    

    【讨论】:

      【解决方案3】:

      事实证明,一旦我添加了用户的角​​色,我需要重新对用户进行身份验证。

              $token = new UsernamePasswordToken(
                  $user,
                  null,
                  'main',
                  $user->getRoles()
              );
      
              $this->container->get('security.context')->setToken($token);
      

      【讨论】:

        猜你喜欢
        • 2013-10-31
        • 1970-01-01
        • 2015-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多