Symfony2安全性 - 用户“Ibw \ UserBundle \ Entity \ User”没有用户提供程序

时间:2013-10-26 01:07:54

标签: php security symfony doctrine-orm

我正在为User实体创建自定义实体提供程序。但是当我在登录表单中输入用户名和密码时,我得到了这个例外:

There is no user provider for user "Ibw\UserBundle\Entity\User".

当我切换回默认的Doctrine实体提供程序时,一切顺利。

首先是我的security.yml

security:
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        secured_area:
            pattern:    ^/
            anonymous: ~
            form_login:
                login_path:   /login
                check_path:   /login_check
                default_target_path:  ibw_job_index
            logout:
                path:   /logout
                target: /

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }

    providers:
        default_provider:
            entity: { class: Ibw\UserBundle\Entity\User }

    encoders:
        Ibw\UserBundle\Entity\User: sha512

这是Ibw\UserBundle\Entity\User类:

<?php
namespace Ibw\UserBundle\Entity;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class User
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="Ibw\UserBundle\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    protected $username;

    /**
     * @ORM\Column(type="string", length=40)
     */
    protected $salt;

    /**
     * @ORM\Column(type="string", length=128)
     */
    protected $password;

    public function __construct(ContainerInterface $container)
    {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
        $this->container = $container;
    }

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

    public function setPassword($password)
    {
        $encoder = $this->container->get('security.encoder_factory')->getEncoder($this);
        $this->password = $encoder->encodePassword($password, $this->getSalt());
        return $this;
    }

    /**
     * @return Role[] The user roles
     */
    public function getRoles()
    {
        return array('ROLE_ADMIN');
    }

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

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

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

    public function eraseCredentials()
    {
        // TODO: Implement eraseCredentials() method.
    }

    public function serialize()
    {
        return serialize(array($this->id));
    }

    public function unserialize($serialized)
    {
        list($this->id) = unserialize($serialized);
    }


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

    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }
}

最后,这是我的Ibw\UserBundle\Repository\UserRepository课程:

<?php

namespace Ibw\UserBundle\Repository;

use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserRepository extends EntityRepository implements UserProviderInterface
{

    public function loadUserByUsername($username)
    {
        $q = $this->createQueryBuilder('u')
                    ->select('u')
                    ->where('u.username = :username')
                    ->setParameter('username', $username)
                    ->getQuery();

        try
        {
            $user = $q->getSingleResult();
        }
        catch (NoResultException $e)
        {
            $message = sprintf('Unable to find active admin identified by %s', $username);
            throw new UsernameNotFoundException($message, 0, $e);
        }
        return $user;
    }


    public function refreshUser(UserInterface $user)
    {
        $class = get_class($user);
        if(!$this->supportsClass($user))
        {
            $message = sprintf('Unsupported class type : %s', $class);
            throw new UnsupportedUserException($message);
        }

        return $this->find($user->getId());
    }


    public function supportsClass($class)
    {
        return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
    }
}

修改

我也尝试在JobeetBundle/Resources/config/services.yml

中将其定义为服务
parameters:
    ibw.user.provider.class: Ibw\UserBundle\Repository\UserRepository
    ibw.user.provider.entity.class: Ibw\UserBundle\Entity\User

services:
    ibw.user.provider:
        class: %ibw.user.provider.class%
        factory_service: doctrine
        factory_method: getRepository
        arguments:
            - %ibw.user.provider.entity.class%

jobeet/app/config/security.yml

providers:
    default_provider:
         id: ibw.user.provider
encoders:
    Ibw\UserBundle\Entity\User: sha512

但不幸的是,在我发布登录表单后,它给了我完全相同的错误。

2 个答案:

答案 0 :(得分:7)

我在ContextListener课程中跟踪了这个问题,结果发现这是一个错字!

在这里:

public function refreshUser(UserInterface $user)
{
    $class = get_class($user);
    if (!$this->supportsClass($user)) { //This should be $class not $user
        $message = sprintf('Unsupported class type : %s', $class);
        throw new UnsupportedUserException($message);
    }

    return $this->find($user->getId());
}

if更改为:

if (!$this->supportsClass($class)) {}

答案 1 :(得分:0)

您需要在用户提供商的定义中使用IbwUserBundle:User表示法而不是entity: { class: Ibw\UserBundle\Entity\User },或者只需将用户提供商定义为服务并使用其名称。