在Symfony2中忽略了getRoles()

时间:2014-11-28 09:08:26

标签: security symfony acl fosuserbundle roles

我的安全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表。以下是连接表的示例。

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的调试部分我可以看到实际上我的用户没有成员角色。

no member role

是否有一个我错过的步骤告诉Symfony我分配给我的用户的角色,似乎确保getRoles()返回正确的数组并不像我预期的那样工作。

3 个答案:

答案 0 :(得分:2)

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

为此,您必须为EquatableInterface课程实施User

然后,实现以下方法:

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方法,你可以检查一下   你想要的属性。除非你理解这一点,否则你可能不会   需要实现这个界面或担心它。

答案 1 :(得分:0)

更改

role_hierarchy:
    ROLE_USER:        ROLE_MEMBER

role_hierarchy:
    ROLE_MEMBER:      ROLE_USER

答案 2 :(得分:0)

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

        $token = new UsernamePasswordToken(
            $user,
            null,
            'main',
            $user->getRoles()
        );

        $this->container->get('security.context')->setToken($token);