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
No te sirve colocar los dos campos necesarios para iniciar sesión en la misma entidad???
@miguelplazasr
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
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
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
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
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
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
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
Hola @manuel_j555
Gracias por la información, perfecto, es fácil, crei que debía respetar el $userProvider.
Gracias.
@ramiroanacona
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