Symfony2 User must return UserInterface object on login

I am actually trying to create a login form that matches my database.

The form works well, but I have a problem with UserRepository

. Symfony tells me the following error:

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

      

But as you can see below, my custom entity is implemented UserInterface

, so I don't really understand what this error is.

My custom object:

    <?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 '';
        }

    }

      

My custom repository:

    <?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';
        }
    }

      

And my 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 }

      

Thank you so much!

+3


source to share


2 answers


It looks like your problem is here:

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()

is probably returning a cursor / result set, not a single row as you intended (even if the result set only contains one row).



Try using $this->findOneBy()

this instead.

Based on your code, it looks like you are following the cookbook's guide on How to Load Security Users from a Database (Entity Provider) - but if you don't, it's a useful resource in this case.

+3


source


Caveat: I am far from being an S2 security expert. I just post what works for me.

Your config file doesn't say anything about the system using ImUserRepository as service provider. So the system basically tries to use the default provider. Moreover, using a repository is problematic at best. Doctrine repos can only come from Doctrine entity managers, so you are asking the system to say that my custom class is a doctrine object, so I have to use a repository, and I assume I will be using that entity manager. Will not happen.

Make your user provider a service, and then inject the entity manager into it.

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>

      



You probably also want to encode your passwords in the end like this:

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>

      

And that should force you.

0


source







All Articles