Symfony2 用户提供者必须在登录时返回一个 UserInterface 对象

3

我正在尝试创建一个与我的数据库匹配的登录表单。

表单工作正常,但是我在使用UserRepository时遇到了问题。Symfony 给出以下错误:

The user provider must return a UserInterface object.
exception 'Symfony\Component\Security\Core\Exception\AuthenticationServiceException' with message 'The user provider must return a UserInterface object.' in C:\wamp\www\php\Promocast\Symfony\vendor\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider.php:101

但是正如您在下面看到的,我的用户实体是由UserInterface实现的,所以我真的不明白这里的错误在哪里。

我的用户实体:

    <?php

    namespace Promocast\UtilisateurBundle\Entity;

    use Symfony\Component\Security\Core\User\UserInterface;
    use Doctrine\ORM\Mapping as ORM;

    /**
     * Promocast\UtilisateurBundle\Entity\ImUser
     * 
     * @ORM\Entity(repositoryClass="Promocast\UtilisateurBundle\Entity\ImUserRepository")
     */
    class ImUser implements UserInterface
    {

        /**
        * Here all my var and getter/setter
        * ...
        */

        /**
         * Fonctions UserInterface
         * 
         */
        public function eraseCredentials()
        {
        }
        public function getRoles()
        {
            return $this->idrole;
        }
        public function equals(UserInterface $user)
        {
            return $user->getUsername() === $this->login;
        }
        public function getUsername()
        {
            return $this->login;
        }
        public function getSalt()
        {
            return '';
        }

    }

我的用户存储库:

    <?php

    namespace Promocast\UtilisateurBundle\Entity;

    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;
    use Doctrine\ORM\EntityRepository;
    use Doctrine\ORM\NoResultException;

    class ImUserRepository extends EntityRepository implements UserProviderInterface
    {
        public function loadUserByUsername($login)
        {
            $user = $this->findBy(array("login" => $login));

            if (!$user) {
                throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $login));
            }

            return $user;
        }

        public function refreshUser(UserInterface $user)
        {
            return $this->loadUserByUsername($user->getUsername());
        }

        public function supportsClass($class)
        {
            return $class === 'Promocast\UtilisateurBundle\Entity\ImUser';
        }
    }

以下是我的security.yml文件:

    security:
        encoders:
            Promocast\UtilisateurBundle\Entity\ImUser: plaintext
            #Promocast\UtilisateurBundle\Security\Provider\LoginWebService: plaintext

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

        providers:
            main:
                entity: { class: PromocastUtilisateurBundle:ImUser }
                #entity: { class: Promocast\UtilisateurBundle\Entity\ImUser, property: login }
                #id: webservice_user_provider


        firewalls:
            dev:
                pattern:  ^/(_(profiler|wdt)|css|images|js)/
                security: false
            login:
                pattern:   ^/(login$|register|resetting) 
                anonymous: true                          
            main:
                pattern: ^/                      
                form_login:                      
                    login_path: /login              
                    check_path: /login_check            
                    username_parameter: _login
                    password_parameter: _password
                remember_me:
                    key:         %secret%       
                anonymous:       true           
                provider:        main
                logout:          true            
                logout:
                    path: /logout
                    target: /

        access_control:
            #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
            #- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
            #- { path: /.*, role: ROLE_USER }
            #- { path: /login, role: IS_AUTHENTICATED_ANONYMOUSLY }

非常感谢!
2个回答

4

看起来你的问题出在这里:

public function loadUserByUsername($login)
{
    $user = $this->findBy(array("login" => $login));
    if (!$user) {
        throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $login));
    }

    return $user;
}

$this->findBy()可能返回的是游标/结果集而不是你所期望的单行数据(即使结果集只包含一行)。

尝试使用$this->findOneBy()

根据你的代码,看起来你正在遵循Symfony文档中的如何从数据库加载安全用户(实体提供器)教程。但如果没有,这也是一个有用的资源。


非常感谢,你解决了我的问题!我正在按照食谱操作,我发现使用DQL请求时,我的实体存储库可以正常工作,所以我猜想findby方法在这种情况下不起作用!再次感谢! - Snroki

0

注意:我并不是S2安全系统的专家,我只是发布了对我有效的内容。

你的配置文件中没有任何内容告诉系统使用ImUserRepository作为用户提供者。因此,系统基本上尝试使用默认提供者。此外,使用存储库最好避免问题。Doctrine repos只能来自Doctrine实体管理器,因此你要求系统说:“嘿,我的用户类是一个Doctrine实体,因此我应该使用一个存储库,我猜我会使用这个实体管理器。” 这是不可能的。

将你的用户提供者设置为服务,然后将实体管理器注入其中。

security:
    providers:
        my_provider:
            id: zayso_core.user.provider


    <service id="zayso_core.user.provider" class="Zayso\CoreBundle\Component\User\UserProvider" public="true">
        <argument type="service" id="doctrine.orm.accounts_entity_manager" />
        <argument type="string">%zayso_core.user.class%</argument>
    </service>

您可能最终也想编码您的密码,以便更安全:

security:
    encoders:
        Zayso\AreaBundle\Component\User\User:
            id: zayso_core.user.encoder


    <service id="zayso_core.user.encoder" class="Zayso\CoreBundle\Component\User\Encoder" public="true">
    </service>

这样应该能让你开始了。


可能是这样,但问题是我在用户实体中调用了我的存储库: * @ORM\Entity(repositoryClass="Promocast\UtilisateurBundle\Entity\ImUserRepository")但还是谢谢您的回答! - Snroki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接