Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

[SOLUCIONADO] Problema con UserProvider en Silex con DoctrineORM

23 de julio de 2015

Muy buenas, he seguido el tutorial completo de este magnifico portal. Me ha servido de mucho pero estoy atascado en el tema de los usuarios.

Utitilizo Silex-Skeleton en su versión mas reciente, además utilizo DoctrineORM para la base de datos.

He tenido que crear un UserProvider, he comprobado que me llega bien el nombre de usuario y realiza la consulta perfectamente, así que creo que está todo bien aquí.

// Silex/Providers/UserProvider.php
namespace Providers;
 
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
class UserProvider implements UserProviderInterface
{
    private $app;
    public function __construct(\Silex\Application $app)
    {
        $this->app = $app;
    }
 
    public function loadUserByUsername($username){
        //print_r($username);
 
        $em = $this->app["orm.ems"]['local'];
        if($em instanceof \Doctrine\ORM\EntityManager){
            if(!$user = $em->getRepository("Entity\User")->findOneBy(array("username"=>$username))){
                throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
            }
        }
 
        //print_r($user); die();
        return $user;
    }
 
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof \Entity\User) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
        }
        return $this->loadUserByUsername($user->getUsername());
    }
 
    public function supportsClass($class)
    {
        return $class === '\Entity\User';
    }
}

Este es mi archivo app.php, dispongo de dos bases de datos y también dispongo de dos tipos de ROLES. El primer ROLE_ADMIN trae los usuarios del UserProvider y es aquí donde falla. No loguea, no lo entiendo. Por otro lado, mas abajo, en ROLE partner, obtengo el usuario y contraseña sin UserProvider y si que me loguea bien, por tanto, no entiendo que está pasando. Las contraseñas estan bien codificadas, he probado con todo y no doy con la solución. A ver si alguien puede exarme una mano. Un saludo y muchas gracias de antemano!!

use Silex\Application;
use Silex\Provider\TwigServiceProvider;
use Silex\Provider\ValidatorServiceProvider;
use Silex\Provider\ServiceControllerServiceProvider;
use Silex\Provider\HttpFragmentServiceProvider;
 
use Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider;
use Silex\Provider\DoctrineServiceProvider;
//use Lib\Provider\UserProvider;
use Silex\Provider\SecurityServiceProvider;
 
//use Silex\Provider\UrlGeneratorServiceProvider; //obsoleto Silex V2.0
use Silex\Provider\RoutingServiceProvider;
use Silex\Provider\SessionServiceProvider;
 
use Symfony\Component\Routing\Generator\UrlGenerator;
 
use Providers\UserProvider;
 
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
 
$app = new Application();
$app->register(new RoutingServiceProvider());
$app->register(new Silex\Provider\RoutingServiceProvider());
$app->register(new ValidatorServiceProvider());
$app->register(new ServiceControllerServiceProvider());
$app->register(new TwigServiceProvider());
$app->register(new HttpFragmentServiceProvider());
$app['twig'] = $app->extend('twig', function ($twig, $app) {
    // add custom globals, filters, tags, ...
    $twig->addFunction(new \Twig_SimpleFunction('asset', function ($asset) use ($app) {
        return $app['request_stack']->getMasterRequest()->getBasepath().'/'.ltrim($asset, '/');
    }));
    return $twig;
});
 
/*======================= DOCTRINE ORM ==========================
 *
 * FUENTE: https://github.com/dflydev/dflydev-doctrine-orm-service-provider
 */
$app->register(new SessionServiceProvider());
 
$app->register(new Silex\Provider\DoctrineServiceProvider(), array(
    'dbs.options'    => array(
        'local' => array( //base de datos local
                'driver'    => 'pdo_mysql',
                'host'      => 'localhost',
                'dbname'    => 'silex',
                'user'      => 'root',
                'password'  => '',
                'charset'   => 'utf8',
                'driverOptions' => array(1002 => 'SET NAMES utf8'),
        ),
        'remote' => array( //base de datos remota
               'driver'    => 'pdo_mysql',
               'host'      => '',
               'dbname'    => '',
               'user'      => '',
               'password'  => '',
               'charset'   => 'utf8',
               'driverOptions' => array(1002 => 'SET NAMES utf8'),
        ),
    ),
));
 
$app->register(new Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
    "orm.ems.default" => "local",
    "orm.ems.options" => array(
        "local" => array(
            "connection" => "local",
            "mappings" => array(
                array(
                    "type"      => "yml",
                    "namespace" => "Entity",
                    "path"      => realpath(__DIR__."/../config/doctrine"),
                ),
            ),
        ),
        "remote" => array(
            "connection" => "remote",
            "mappings" => array(
                array(
                    "type"      => "yml",
                    "namespace" => "Entity",
                    "path"      => realpath(__DIR__."/../config/doctrine"),
                ),
            ),
        ),
 
    ),
));
 
/*========================== USERS =============================*/
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls'    => array(
 
        'dev' => array(
                    'pattern' => '^/(_(profiler|wdt)|css|img|js)/', 
                    'security' => false),
 
        //Reglas para el admin
        'admin' => array(
                    'pattern'     => '^/admin/panel',
                    'http'        => true,
                    'form'        => array(
                                        'login_path' => '/admin',
                                        'check_path' => '/admin/panel/login_check',
                                        'default_target_path' => "/admin/panel", //url de redireccion
                                        'always_use_default_target_path' => true,
                                        'username_parameter'  =>  '_username', 
                                        'password_parameter'  =>  '_password'
                                        ),
                    'anonymous'  =>  false , 
                    /*'users' => array(
                        'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
                    ),*/
                    'users'       => function ($app) {
                       return new \Providers\UserProvider($app);
                    },
                    'logout' => array(
                        'logout_path' => '/admin/panel/logout'),
                        'invalidate_session' => false
                    ),
 
        //Reglas para el partner
        'partner' => array(
                    'pattern'     => '^/partner',
                    'http'        => true,
                    'form'        => array(
                                        'login_path' => '/',
                                        'check_path' => '/partner/login_check',
                                        'default_target_path' => "/partner", //url de redireccion
                                        'always_use_default_target_path' => true,
                                        'username_parameter'  =>  '_username', 
                                        'password_parameter'  =>  '_password'
                                        ),
                    'anonymous'  =>  false , 
                    'users' => array(
                        'partner' => array('ROLE_PARTNER', '5FZ2Z8.....4FOBiiFyLfuZmTSUwzZg=='),
                    ),
                    /*'users'       => function ($app) {
                        return new \Providers\UserProvider($app);
                    },*/
                    'logout' => array(
                        'logout_path' => '/partner/logout'),
                        'invalidate_session' => false
                    ),
 
    ),
    'security.encoders'  => array(
        'Entity\User'=> array(
            'algorithm'        => 'sha1',
            'iterations'       => 4,
            'encode_as_base64' => false
        )
    )
));
 
$app['user.options'] = array(
    //'templates' => array(
    //    'layout' => 'layout.twig',
    //    'view' => 'view.twig',
    //),
    'mailer' => array('enabled' => false),
    'userClass' => 'Entity\User',
);
 
/*$app['security.role_hierarchy'] = array(
    'ROLE_ADMIN' => array('ROLE_PARTNER', 'ROLE_ALLOWED_TO_SWITCH'),
);*/
 
$app['security.access_rules'] = array( //Especificando los ROLES
    array('^/admin/panel', 'ROLE_ADMIN', 'http'),
    array('^/partner', 'ROLE_PARTNER','http'),
);
 
return $app;

NOTA: En el UserProvider, he colocado un PRINT_R($user) en la función LoadUserByUsername().El resultado es el siguiente:

Entity\User Object (
  [id_user:Entity\User:private] => 1
  [username:Entity\User:private] => admin2
  [email:Entity\User:private] => [email protected]
  [password:Entity\User:private] => 5FZ2Z8QIkA7UTZ4BYkoC+.......==
  [roles:Entity\User:private] => ROLE_ADMIN )

Entiendo, que ha realizado la consulta a la base de datos a través de la entidad USER, ha buscado por el usuario ADMIN2 y lo ha encontrado y por ende saca la CONTRASEÑA y el ROLE. Hasta aquí puede que todo OK peeeero...cuando hace el return ya a partir de ahí...no funciona.

Igual esto puede ayudar un poco, no se si lo que devuelve esta bien...porque como no funciona...pues no se qué pensar, estoy empezando con Silex y Doctrine y estoy aprediendo aún. Un saludo!!


Respuestas

#1

Hola, podrías intentar con algo así

...
 
'admin' => array(
    'pattern' => '^/admin',
    'anonymous' => true,
    'form' => array(
        'login_path' => '/admin/login',
        'check_path' => '/admin/login_check',
        'default_target_path' => '/admin/panel',
        'always_use_default_target_path' => true,
    ),
    'logout' => array(
        'logout_path' => '/admin/logout',
        'target_url' => '/admin',
    ),
    'users' => function ($app) {
        return new \Providers\UserProvider($app);
    },
),
 
// ...
 
$app['security.access_rules'] = array(
    array( '^/admin/login', 'IS_AUTHENTICATED_ANONYMOUSLY', ),
    array( '^/admin*', 'ROLE_ADMIN', ),
    array( '^/partner', 'ROLE_PARTNER', ),
);

Saludos.

@iBet7o

24 julio 2015, 3:07
#2

Muchas gracias @iBet7o.

He realizado los cambios que me dices y nada, sigue igual, a ti te funciona bien tu código?? utilizas DoctrineORM ??

Un saludo!

@daviz_xtr

24 julio 2015, 9:39
#3

ya esta solucionado, por si alguno le pasa y le puede ayudar.

Se me olvido implementar UserInterface en Entity/User.

<?php
 
namespace Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User implements UserInterface
{

Ademas me daba errores con los ROLES, la solucion ha sido colocar:

/**
     * Get roles
     *
     * @return string
     */
    public function getRoles()
    {
        return array($this->roles);
    }

@daviz_xtr

24 julio 2015, 13:01
#4

ya esta solucionado, por si alguno le pasa y le puede ayudar.

Se me olvido implementar UserInterface en Entity/User.

<?php
 
namespace Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User implements UserInterface
{

Ademas me daba errores con los ROLES, la solucion ha sido colocar:

/**
     * Get roles
     *
     * @return string
     */
    public function getRoles()
    {
        return array($this->roles);
    }

@daviz_xtr

24 julio 2015, 13:01
#5

ya esta solucionado, por si alguno le pasa y le puede ayudar.

Se me olvido implementar UserInterface en Entity/User.

<?php
 
namespace Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User implements UserInterface
{
 
//...

Ademas me daba errores con los ROLES, la solucion ha sido colocar:

//...
     /**
     * Get roles
     *
     * @return string
     */
    public function getRoles()
    {
        return array($this->roles);
    }
    //...

Con estos cambios ya funciona correctamente SILEX con DoctrineORM.

@daviz_xtr

24 julio 2015, 13:03