如何在Silex中使用自定义用户提供程序?

时间:2015-01-02 23:51:28

标签: php silex runtimeexception doctrine-odm doctrine-mongodb

我真的可以使用第二双眼睛。我正在尝试使用Silex的SecurityServiceProvider和Doctrine MongoDB ODM创建自定义用户提供程序,并且在尝试登录时仍然收到以下错误:

RuntimeException in ContextListener.php line 177:
There is no user provider for user "FooBar\Document\User".

注意:如果我对用户进行硬编码,则效果很好

'users' => [
    'admin' => [
        'ROLE_ADMIN', '$2y$12$W6FYYG1YTdMUNSosk14jluYsCwTe5wL7qwi3bnRMsqQEShb.89OiG'
    ],
]

据我所知,我遵循了Silex文档,可以找到here。我验证它是从db中成功获取用户的,所以我知道这不是问题。以下是相关代码,包括来自app.php的片段,用户类和我的自定义用户提供程序类。

$app->register(new Neutron\Silex\Provider\MongoDBODMServiceProvider(), $dbConfig);

// Create document manager alias
$app['dm'] = $app['doctrine.odm.mongodb.dm'];

$app->register(new Silex\Provider\SecurityServiceProvider(), [
    'security.firewalls' => [
        'login' => [
            'pattern' => '^/login$',
            'anonymous' => true
        ],
        'secured' => [
            'pattern' => '^.*$',
            'form' => [
                'login_path' => '/login',
                'check_path' => '/login/authenticate',
            ],
            'logout' => [
                'logout_path' => '/logout',
                'target' => '/'
            ],
            'users' => $app->share(function() use ($app) {
                return new \FooBar\Repository\UserRepository($app['dm']);
            })
        ],
        'unsecured' => [
            'anonymous' => true
        ]
    ],
    'security.role_hierarchy' => [
        'ROLE_ADMIN' => [
            'ROLE_USER',
        ],
        'ROLE_SUPER_ADMIN' => [
            'ROLE_ADMIN',
            'ROLE_ALLOWED_TO_SWITCH'
        ]
    ],
    'security.access_rules' => [
        ['^/login', 'IS_AUTHENTICATED_ANONYMOUSLY'],
        ['^.*', 'ROLE_USER']
    ]
]);

$app['security.encoder.digest'] = $app->share(function() {
    return new Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder(12);
});

namespace FooBar\Repository;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

class UserRepository implements UserProviderInterface
{
    public function loadUserByUsername($username)
    {
        try {

            $user = $this->dm->createQueryBuilder('\FooBar\Document\User')
                ->field('username')->equals($username)
                ->getQuery()
                ->getSingleResult();

        } catch (NoResultException $e) {

            throw new UsernameNotFoundException(sprintf(
                'Unable to find an active User object identified by "%s".',
                $username
            ), 0, $e);

        }

        return $user;
    }

    public function refreshUser(UserInterface $user)
    {
        $class = get_class($user);

        if (!$this->supportsClass($class)) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $class));
        }

        return $this->loadUserByUsername($user->getUsername());
    }

    public function supportsClass($class)
    {
        return $class === '\FooBar\Document\User' || is_subclass_of($class, '\FooBar\Document\User');
    }
}

<?php

namespace FooBar\Document;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;

/**
 * @ODM\Document(repositoryClass="FooBar\Repository\UserRepository")
 */
class User implements AdvancedUserInterface
{
    /**
     * Document Id
     * @ODM\Id
     */
    protected $id;

    /**
     * User first name
     * @ODM\String
     */
    protected $firstName;

    /**
     * User last name
     * @ODM\String
     */
    protected $lastName;

    /**
     * User email
     * @ODM\String
     * @ODM\UniqueIndex
     */
    protected $email;

    /**
     * User username
     * @ODM\String
     * @ODM\UniqueIndex
     */
    protected $username;

    /**
     * User password
     * @ODM\String
     */
    protected $password;

    /**
     * Whether or not user account is expired
     * @ODM\Boolean
     */
    protected $isAccountExpired;

    /**
     * Whether or not user account is locked
     * @ODM\Boolean
     */
    protected $isAccountLocked;

    /**
     * Whether or not user credentials are expired
     * @ODM\Boolean
     */
    protected $isCredentialsExpired;

    /**
     * Whether or not user is active
     * @ODM\Boolean
     */
    protected $isActive;

    /**
     * Whether or not user credentials are erased
     * @ODM\Boolean
     */
    protected $isCredentialsErased;

    /**
     * User roles
     * @ODM\Collection
     */
    protected $roles;
/
    public function __construct()
    {
        parent::__construct();
        $this->isActive = true;
        $this->isAccountLocked = false;
        $this->isAccountExpired = false;
        $this->isCredentialsExpired = false;
        $this->isCredentialsErased = false;
        $this->roles = new ArrayCollection;

        // Temporary
        $this->roles = ['ROLE_USER'];
    }

    public function setFirstName($firstName)
    {
        $this->firstName = $firstName;
    }

    public function setLastName($lastName)
    {
        $this->lastName = $lastName;    
    }

    public function setEmail($email)
    {
        $this->email = ($email);
    }

    public function setUsername($username)
    {
        $this->username = $username;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }

    public function getFirstName()
    {
        return $this->firstName;
    }

    public function getLastName()
    {
        return $this->lastName;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getSalt()
    {
        return null;
    }

    public function getRoles()
    {
        return $this->roles;
    }

    public function isAccountNonExpired()
    {
        return !$this->isAccountExpired;
    }

    public function isAccountNonLocked()
    {
        return !$this->isAccountLocked;
    }

    public function isCredentialsNonExpired()
    {
        return !$this->isCredentialsExpired;
    }

    public function isCredentialsErased()
    {
        return $this->isCredentialsErased;
    }

    public function isEnabled()
    {
        return $this->isActive;
    }

    public function eraseCredentials()
    {
        $this->username = null;
        $this->password = null;
        $this->isActive = false;
        $this->isAccountLocked = true;
        $this->isAccountExpired = true;
        $this->isCredentialsExpired = true;
        $this->isCredentialsErased = true;

        return $this;
    }

    public function serialize()
    {
        return serialize([
            $this->id,
            $this->firstName,
            $this->lastName,
            $this->email,
            $this->username,
        ]);
    }

    public function unserialize($serialized)
    {
        list(
            $this->id,
            $this->firstName,
            $this->lastName,
            $this->email,
            $this->username,
        ) = unserialize($serialized);
    }
}

1 个答案:

答案 0 :(得分:2)

get_class($user);

将返回

FooBar\Document\User

而不是

\FooBar\Document\User

所以,替换

$class === '\FooBar\Document\User'

通过

$class === 'FooBar\Document\User'