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

Login compuesto

11 de septiembre de 2015

Hola qué tal? Les hago una consulta, resulta que estoy necesitando desarrollar un formulario de login que permita iniciar sesión por dos campos:

  • DNI.
  • Correo electrónico.

Actualmente en mi security.yml tengo:

providers:
        usuarios_db:
            entity: { class: EM\UsuariosBundle\Entity\Usuario, property: username }

Para que pueda iniciar sesión por DNI o email simplemente se debe agregar:

providers:
        usuarios_db:
            entity: { class: EM\UsuariosBundle\Entity\Usuario, property: dni, correo }

o

providers:
        usuarios_db:
            entity: { class: EM\UsuariosBundle\Entity\Usuario, property: [dni, correo] }

Otra cosa, en mi base de datos manejo dos entidades:

Usuario

  • id
  • username
  • password
  • fechaUltimaConexion
  • cantLogin

Perfil

  • idUsuario
  • apellido
  • nombre
  • dni
  • correo

¿Alguna idea de cómo puedo solucionar esto? Desde ya muchas gracias!


Respuestas

#1

No te sirve colocar los dos campos necesarios para iniciar sesión en la misma entidad???

@miguelplazasr

11 septiembre 2015, 23:10
#2

Creo que el problema esta en que tu provider es EM\UsuariosBundle\Entity\Usuario y los campos que tu necesitas para hacer login estan en EM\UsuariosBundle\Entity\Perfil

¿No seria posible que guardases los campos con los que quieres hacer login en usuario?

@TsubasaAkai

11 septiembre 2015, 23:38
#3

Hola, para lograr lo que deseas tienes dos opciones:

Implementar UserProviderInterface en el repositorio:

Debes Crear un repositorio de usuarios UsuarioRepository (si no lo tienes ya claro) y hacer que implemente UserProviderInterface como lo explican en la documentación oficial: http://symfony.com/doc/current/cookbook/security/entity_provider.html#using-a-custom-query-to-load-the-user

Crear tu propio Proveedor de usuarios:

http://symfony.com/doc/current/cookbook/security/custom_provider.html#create-a-user-provider


Saludos!

@manuel_j555

12 septiembre 2015, 0:53
#4

Muchas gracias por sus respuestas, debo decir que la solución que estoy usando es la propuesta por: @manuel_j555

Y la verdad no funciona bien, funciona PERFEEEEECTO!!!! xD

MUCHAS GRACIAS! :D

@MrXXX0323

13 septiembre 2015, 2:33
#5

Hola @manuel_j555 yo he tenido que solucionar algo similar.

Mi pregunta es, ¿cómo capturas el dni en el método loadUserByUsername? Este método solo recibe un parámetro.

Yo busqué en Google y encontré esta solución en StackOverflow.

Por el momento es lo que me ha solucionado el problema pero no se si será la mejor manera de hacerlo.

Gracias.

@ramiroanacona

13 septiembre 2015, 8:12
#6

Hola @ramiroanacona, el asunto es que @MrXXX0323 está usando el mismo campo del username para buscar tanto por dni como por nombre de usuario, por lo que al método loadUserByUsername le llega un unico valor y allí dentro, se busca por un campo o por el otro.

Si tu necesitas manejar más campos que los que ofrece el proveedor de seguridad form_login mi consejo es que implementes tu propio FormAuthenticator haciendo uso del proveedor de seguridad llamado simple_form.

Acá tienes la documentación de como usarlo:

http://symfony.com/doc/current/cookbook/security/custom_password_authenticator.html

Basicamente con esta implementación tienes la posibilidad de leer campos adicionales en el método createToken y allí pasarlos al token que será posteriormente autenticado.

Luego en el método authenticateToken lees esos campos adicionales y haces la busqueda del usuario.

Saludos!

@manuel_j555

14 septiembre 2015, 15:17
#7

Hola @manuel_j555, gracias por la información, he revisado la documentación que mencionas, comprendo la parte del método createToken donde puedo capturar datos adicionales con el parámetro $request y luego acceder a ellos en el método authenticateToken

Hasta aquí no hay problema, mi duda es cómo utilizo ese parámetro adicional?

Yo tengo un UserProvider, al implementar una interfaz obliga a que el método loadUserByUsername solo reciba un parámetro, entonces no se como pasar ese parámetro adicional para cargar mi usuario.

Como usaría ese parámetro adicional para hacer la consulta? Gracias

@ramiroanacona

15 septiembre 2015, 4:29
#8

La ventaja de de tener tu propio Autenticador, es que puedes obviar el uso del UserProvider y utilizar cualquier servicio o repositorio con sus propios métodos para obtener el usuario.

Inyectale a tu servicio Autenticador el UserRepository o el EntityManager, y usa o crea alguna consulta que reciba los dos parametros que necesitas:

<?php
 
class CustomAuthenticator implements SimpleFormAuthenticatorInterface
{
    private $userRepository;
 
    public function __construct(UserRepository $ur)
    {
        $this->userRepository= $ur;
    }
 
    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        // Acá llamas a tu propio método en el repositorio de usuarios.
        $user = $this->userRepository->findOneByUsernameAndXXX(
            $token->getUsername(), $token->getAttribute('xxx')
        );
 
        // Verificar password y demás...
    }
 
    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof UsernamePasswordToken
            && $token->getProviderKey() === $providerKey;
    }
 
    public function createToken(Request $request, $username, $password, $providerKey)
    {
        $token = new UsernamePasswordToken($username, $password, $providerKey);
        $token->setAttribute($request->request->get('xxx'));
 
        return $token;
    }
}

Saludos!

@manuel_j555

15 septiembre 2015, 15:16
#9

Hola @manuel_j555

Gracias por la información, perfecto, es fácil, crei que debía respetar el $userProvider.

Gracias.

@ramiroanacona

15 septiembre 2015, 17:30
#10

En mi caso lo que hice fue simple.

1) Modifique el registro de usuarios, en un principio pedía los campos:

  • nombre de usuario.
  • correo
  • contraseña
  • repetir contraseña.

La idea de de que se permita iniciar sesión con dni o correo electrónico hace que la comunicación o interacción entre el sitio y el usuario sea más personalizada y amigable, por lo que al Form de registro de usuario lo cambie de la siguiente manera:

  • Nombre
  • Apellido
  • DNI
  • Correo
  • contraseña
  • repetir contraseña.

el campo DNI lo utilizo como username y el campo correo como correo, los campos apellido y nombre los utilizo para inmediatamente generar la entidad Perfil y setearle éstos valores, para que cuando el usuario ingrese al sitio aparezca un mensaje de bienvenida que diga: ¡Bienvenido Apellido, Nombre!

Entonces cuando te logueas en el método: loadUserByUsername directamente haces una consulta que busque por los campos username o correo de la entidad Usuario, pero sino deseas manejarlo de esta manera, tmb. en la consulta podes hacer un join con tu entidad perfil y seguir buscando por los campos que desees.

@MrXXX0323

17 septiembre 2015, 21:33