117 votes

Authentification automatique des utilisateurs après l'enregistrement

Nous avons créé une application métier à partir de zéro dans Symfony 2, et le flux d'enregistrement de l'utilisateur me pose problème: une fois que l'utilisateur a créé un compte, il doit être automatiquement connecté avec ces informations d'identification. d'être immédiatement obligés de fournir à nouveau leurs informations d'identification.

Quelqu'un en a-t-il déjà fait l'expérience ou est-il capable de me diriger dans la bonne direction?

147voto

Chausser Points 2736

Symfony 2.3.x

Pour ce faire dans symfony 2.3 vous ne pouvez plus juste de définir le jeton dans le contexte de sécurité. Vous devez également enregistrer le jeton de la session.

En supposant un fichier de sécurité avec un pare-feu comme:

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

Et l'action d'un contrôleur de semblable aussi:

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
    }

}

Pour le jeton de la création que vous souhaitez créer un UsernamePasswordToken, Ce accepte 4 paramètres: Entité Utilisateur, les informations d'Identification Utilisateur, Pare-feu Nom, les Rôles d'Utilisateur. Vous n'avez pas besoin de fournir à l'utilisateur des informations d'identification pour le jeton pour être valide.

Je ne suis pas sûr à 100% que la définition du jeton sur l' security.context est nécessaire si vous allez juste pour rediriger tout de suite. Mais il ne semble pas mal donc je l'ai laissé.

Puis, la partie importante, la définition de la variable de session. Les variables convention de nommage est - _security_ suivi par votre pare-feu nom, dans ce cas - main faire _security_main

65voto

Problematic Points 10229

Pensé que ça, finalement.

Après l'enregistrement de l'utilisateur, vous devez avoir accès à un objet instanceof tout ce que vous avez défini comme entité utilisateur de votre fournisseur de configuration. La solution est de créer un nouveau jeton de l'utilisateur de l'entité et la passer dans le contexte de sécurité. Voici un exemple basé sur ma configuration:

RegistrationController.php:

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

main est le nom du pare-feu pour votre application (merci, @Joe). C'est vraiment tout là est à lui; aujourd'hui, le système considère que votre utilisateur connecté en tant qu'utilisateur ils ont juste créé.

EDIT: Par @Miquel commentaire, j'ai mis à jour le contrôleur de l'exemple de code pour inclure un bon rôle par défaut pour les nouveaux utilisateurs (bien que de toute évidence ce qui peut être ajusté selon vos besoins spécifiques).

6voto

Cédric Nirousset Points 146

Si vous avez un objet UserInterface (et cela devrait être le cas la plupart du temps), vous pouvez utiliser la fonction getRoles qu'elle implémente pour le dernier argument. Donc, si vous créez une fonction logUser, elle devrait ressembler à ça:

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

6voto

Sam Hanes Points 1264

Je suis à l'aide de Symfony 2.2 et mon expérience légèrement différente de celle - Problématique de l', c'est donc une version combinée de toutes les infos de cette question, en plus de certains de mes propres.

Je pense que Joe est trompé sur la valeur de $providerKey, le troisième paramètre de la UsernamePasswordToken constructeur. C'est censé être la clé d'authentification (utilisateur non professionnel. Il est utilisé par le système d'authentification de distinguer entre les jetons créés pour différents fournisseurs. Tout fournisseur qui descend d' UserAuthenticationProvider va authentifier les jetons dont le fournisseur de la clé correspond à son propre. Par exemple, l' UsernamePasswordFormAuthenticationListener définit la clé du jeton qu'il crée pour correspondre à celui de son correspondant, DaoAuthenticationProvider. Qui permet à un seul pare-feu avoir plusieurs nom d'utilisateur+mot de passe prestataires, sans leur marcher sur les autres. Par conséquent, nous devons choisir une clé qui n'entre pas en conflit avec d'autres fournisseurs. J'utilise 'new_user'.

J'ai un peu de systèmes dans d'autres parties de mon application qui dépendent de l' authentification de la réussite de l'événement, et qui n'est pas tiré par la seule définition de l'jeton sur le contexte. J'ai eu pour obtenir l' EventDispatcher du récipient, et le feu de l'événement manuellement. Puis j'ai décidé également de déclencher une connexion interactive de l'événement parce que nous sommes l'authentification de l'utilisateur implicitement, pas de réponse explicite de demande de connexion.

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

Notez que l'utilisation d' $this->get( .. ) suppose l'extrait de code est dans une méthode de contrôleur. Si vous utilisez le code quelque part d'autre, vous aurez à changer les appeler ContainerInterface::get( ... ) d'une manière appropriée à l'environnement. Comme il arrive mon entités utilisateur de mettre en œuvre UserInterface donc je peux l'utiliser directement avec le jeton. Si le vôtre ne pas, vous aurez à trouver un moyen de les convertir en UserInterface des cas.

Ce code fonctionne, mais j'ai l'impression que c'est le piratage autour de Symfony architecture d'authentification plutôt que de travailler avec elle. Il serait sans doute plus correct de mettre en œuvre un nouveau fournisseur d'authentification avec son propre jeton de classe plutôt que de détourner l' UsernamePasswordToken. Aussi, à l'aide d'un bon fournisseur voudrait dire que les événements ont été pris en charge pour vous.

4voto

daemonl Points 354

Au cas où quelqu'un aurait la même question, ce qui m'a fait revenir ici:

Appel

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

n'affecte que le 'security.context' actuel pour la route utilisée.

En d'autres termes, vous ne pouvez connecter un utilisateur qu'à partir d'une URL sous le contrôle du pare-feu.

(Ajoutez une exception pour la route si nécessaire - IS_AUTHENTICATED_ANONYMOUSLY)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X