validación usuarios usuario usando primera parte para múltiples guardar datos crear contraseña con autentificación autenticación autenticacion administrador php symfony registration

php - usuarios - Autenticación de usuario automática posterior al registro



usuario y contraseña php (8)

Estamos construyendo una aplicación de negocios desde cero en Symfony 2, y me he encontrado con un pequeño inconveniente con el flujo de registro de usuarios: después de que el usuario crea una cuenta, deben iniciar sesión automáticamente con esas credenciales, en su lugar de ser forzado de inmediato a proporcionar sus credenciales de nuevo.

¿Alguien ha tenido alguna experiencia con esto, o puede apuntarme en la dirección correcta?


Como problemático aquí ya mencionado, este elusivo $ providerKey parámetro es en realidad nada más que el nombre de su regla de firewall, ''foobar'' en el caso del ejemplo a continuación.

firewalls: foobar: pattern: /foo/


En caso de que alguien tenga la misma pregunta de seguimiento que me mantuvo volviendo a aquí:

Vocación

$this->container->get(''security.context'')->setToken($token);

solo afecta al actual security.context para la ruta utilizada.

Es decir, solo puede iniciar sesión en un usuario desde una url dentro del control del firewall.

(Agregue una excepción para la ruta si es necesario - IS_AUTHENTICATED_ANONYMOUSLY )


En la versión 2.8.11 de Symfony (probablemente funcione para versiones más antiguas y nuevas), si usa FOSUserBundle simplemente haga esto:

try { $this->container->get(''fos_user.security.login_manager'')->loginUser( $this->container->getParameter(''fos_user.firewall_name''), $user, null); } catch (AccountStatusException $ex) { // We simply do not authenticate users which do not pass the user // checker (not enabled, expired, etc.). }

No es necesario enviar el evento como lo he visto en otras soluciones.

inspirado en FOS / UserBundle / Controller / RegistrationController :: authenticateUser

(de la versión de composer.json FOSUserBundle: "friendsofsymfony / user-bundle": "~ 1.3")


Estoy usando Symfony 2.2 y mi experiencia fue ligeramente diferente a la de Problematic''s , así que esta es una versión combinada de toda la información de esta pregunta más algunas de las mías.

Creo que Joe está equivocado sobre el valor de $providerKey , el tercer parámetro para el constructor UsernamePasswordToken . Se supone que es la clave de un proveedor de autenticación (no del usuario). Es utilizado por el sistema de autenticación para distinguir entre tokens creados para diferentes proveedores. Cualquier proveedor que desciende de UserAuthenticationProvider solo autenticará tokens cuya clave de proveedor coincida con la suya. Por ejemplo, UsernamePasswordFormAuthenticationListener establece la clave del token que crea para que coincida con la de su DaoAuthenticationProvider correspondiente. Eso permite que un solo firewall tenga múltiples proveedores de nombre de usuario + contraseña sin que se pisen entre sí. Por lo tanto, debemos elegir una clave que no entre en conflicto con otros proveedores. Yo uso ''new_user'' .

Tengo algunos sistemas en otras partes de mi aplicación que dependen del evento de autenticación exitosa , y que no se activan simplemente configurando el token en el contexto. Tuve que sacar EventDispatcher del contenedor e iniciar el evento manualmente. Decidí no activar también un evento de inicio de sesión interactivo porque estamos autenticando al usuario implícitamente, no como respuesta a una solicitud de inicio de sesión explícita.

use Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken; use Symfony/Component/Security/Core/AuthenticationEvents; use Symfony/Component/Security/Core/Event/AuthenticationEvent; $user = // get a Symfony user instance somehow $token = new UsernamePasswordToken( $user, null, ''new_user'', $user->getRoles() ); $this->get( ''security.context'' )->setToken( $token ); $this->get( ''event_dispatcher'' )->dispatch( AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent( $token ) );

Tenga en cuenta que el uso de $this->get( .. ) supone que el fragmento está en un método de controlador. Si usa el código en otro lugar, deberá cambiarlo para llamar a ContainerInterface::get( ... ) de una manera apropiada para el entorno. Da la casualidad que mis entidades usuarias implementan UserInterface para que pueda usarlas directamente con el token. Si el tuyo no lo hace, tendrás que encontrar la forma de convertirlos a instancias de UserInterface .

Ese código funciona, pero siento que está pirateando la arquitectura de autenticación de Symfony en lugar de trabajar con ella. Probablemente sería más correcto implementar un nuevo proveedor de autenticación con su propia clase de token en lugar de secuestrar el UsernamePasswordToken . Además, usar un proveedor adecuado significaría que los eventos fueron manejados por usted.


Imaginé este, finalmente.

Después del registro del usuario, debe tener acceso a una instancia de objeto de lo que haya establecido como su entidad de usuario en la configuración de su proveedor. La solución es crear un nuevo token con esa entidad de usuario y pasarlo al contexto de seguridad. Aquí hay un ejemplo basado en mi configuración:

RegistrationController.php:

$token = new UsernamePasswordToken($userEntity, null, ''main'', array(''ROLE_USER'')); $this->get(''security.context'')->setToken($token);

Donde main es el nombre del firewall para su aplicación (gracias, @Joe). Eso es todo lo que hay que hacer; el sistema ahora considera que su usuario inició sesión completamente como el usuario que acaba de crear.

EDITAR: el comentario de Per @ Miquel, actualicé la muestra del código del controlador para incluir una función predeterminada sensible para un nuevo usuario (aunque, obviamente, esto se puede ajustar de acuerdo con las necesidades específicas de su aplicación).


Intenté todas las respuestas aquí y ninguna funcionó. La única forma en que pude autenticar a mis usuarios en un controlador es haciendo una subpetición y luego redirigiendo. Aquí está mi código, estoy usando silex pero puedes adaptarlo fácilmente a symfony2:

$subRequest = Request::create($app[''url_generator'']->generate(''login_check''), ''POST'', array(''_username'' => $email, ''_password'' => $password, $request->cookies->all(), array(), $request->server->all()); $response = $app->handle($subRequest, HttpKernelInterface::MASTER_REQUEST, false); return $app->redirect($app[''url_generator'']->generate(''curriculos.editar''));


Si tiene un objeto UserInterface (y ese debería ser el caso la mayor parte del tiempo), es posible que desee utilizar la función getRoles que implementa para el último argumento. Entonces, si creas un logUser de función, debería ser así:

public function logUser(UserInterface $user) { $token = new UsernamePasswordToken($user, null, ''main'', $user->getRoles()); $this->container->get(''security.context'')->setToken($token); }


Symfony 4.0

Este proceso no ha cambiado de Symfony 3 a 4, pero aquí hay un ejemplo que usa el AbstractController recientemente recomendado. Tanto el security.token_storage como los servicios de session están registrados en el método principal getSubscribedServices para que no tenga que agregarlos en su controlador.

use Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken; use Symfony/Bundle/FrameworkBundle/Controller/AbstractController; use YourNameSpace/UserBundle/Entity/User; class LoginController extends AbstractController{ public function registerAction() { $user = //Handle getting or creating the user entity likely with a posted form $token = new UsernamePasswordToken($user, null, ''main'', $user->getRoles()); $this->container->get(''security.token_storage'')->setToken($token); $this->container->get(''session'')->set(''_security_main'', serialize($token)); // The user is now logged in, you can redirect or do whatever. } }

Symfony 2.6.x - Symfony 3.0.x

A partir de Symfony 2.6 security.context está en desuso en favor de security.token_storage . El controlador ahora puede simplemente ser:

use Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken; use Symfony/Bundle/FrameworkBundle/Controller/Controller; use YourNameSpace/UserBundle/Entity/User; class LoginController extends Controller{ public function registerAction() { $user = //Handle getting or creating the user entity likely with a posted form $token = new UsernamePasswordToken($user, null, ''main'', $user->getRoles()); $this->get(''security.token_storage'')->setToken($token); $this->get(''session'')->set(''_security_main'', serialize($token)); } }

Si bien esto está obsoleto, aún puede usar security.context ya que se ha creado para que sea compatible con versiones anteriores. Solo prepárate para actualizarlo para Symfony 3

Puede leer más acerca de los 2.6 cambios de seguridad aquí: https://github.com/symfony/symfony/blob/2.6/UPGRADE-2.6.md

Symfony 2.3.x

Para lograr esto en Symfony 2.3 ya no puede simplemente configurar el token en el contexto de seguridad. También necesita guardar el token en la sesión.

Asumiendo un archivo de seguridad con un firewall como:

// app/config/security.yml security: firewalls: main: //firewall settings here

Y una acción de controlador similar también:

use Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken; use Symfony/Bundle/FrameworkBundle/Controller/Controller; use YourNameSpace/UserBundle/Entity/User; class LoginController extends Controller{ public function registerAction() { $user = //Handle getting or creating the user entity likely with a posted form $token = new UsernamePasswordToken($user, null, ''main'', $user->getRoles()); $this->get(''security.context'')->setToken($token); $this->get(''session'')->set(''_security_main'',serialize($token)); //Now you can redirect where ever you need and the user will be logged in } }

Para la creación de tokens, querrá crear un UsernamePasswordToken . Esto acepta 4 parámetros: User Entity, User Credentials, Firewall Name, User Roles. No es necesario que proporciones las credenciales de usuario para que el token sea válido.

No estoy 100% seguro de que configurar el token en el security.context sea ​​necesario si va a redirigir de inmediato. Pero no parece doler así que lo he dejado.

Luego, la parte importante, establecer la variable de sesión. La convención de nomenclatura de variables es _security_ seguido del nombre de su firewall, en este caso main making _security_main