Comprendre le passeport sérialiser désérialiser

337

Comment expliqueriez-vous le flux de travail des méthodes de sérialisation et de désérialisation de Passport à un profane.

  1. user.idaller après passport.serializeUseravoir été appelé?

  2. Nous appelons passport.deserializeUserjuste après, où cela s'intègre-t-il dans le flux de travail?

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

J'essaie toujours d'envelopper ma tête autour de ça. J'ai une application de travail complète et je ne rencontre aucune erreur.

Je voulais juste comprendre ce qui se passe exactement ici?

Toute aide est appréciée.

Anubhav
la source

Réponses:

452
  1. user.idaller après passport.serializeUseravoir été appelé?

L'ID utilisateur (que vous fournissez comme deuxième argument de la donefonction) est enregistré dans la session et est ensuite utilisé pour récupérer l'objet entier via la deserializeUserfonction.

serializeUserdétermine quelles données de l'objet utilisateur doivent être stockées dans la session. Le résultat de la méthode serializeUser est attaché à la session en tant que req.session.passport.user = {}. Ici, par exemple, ce serait (comme nous fournissons l'ID utilisateur comme clé)req.session.passport.user = {id: 'xyz'}

  1. Nous appelons passport.deserializeUserjuste après, où cela s'intègre-t-il dans le flux de travail?

Le premier argument de deserializeUsercorrespond à la clé de l'objet utilisateur qui a été donnée à la donefonction (voir 1.). Ainsi, tout votre objet est récupéré à l'aide de cette clé. Cette clé est ici l'ID utilisateur (la clé peut être n'importe quelle clé de l'objet utilisateur, c'est-à-dire le nom, l'e-mail, etc.). Cette deserializeUserclé correspond à la matrice / base de données en mémoire ou à toute ressource de données.

L'objet récupéré est attaché à l'objet de demande en tant que req.user

Flux visuel

passport.serializeUser(function(user, done) {
    done(null, user.id);
});              
                  
                 
                 └─────────────────┬──→ saved to session
                                       req.session.passport.user = {id: '..'}
                                   
                                              
passport.deserializeUser(function(id, done) {
                   ┌───────────────┘
                   
                    
    User.findById(id, function(err, user) {
        done(err, user);
    });            └──────────────→ user object attaches to the request as req.user   
});
UN B
la source
2
Est donc user.idenregistré sous req.session.passport.userou est userlui - même stocké sous le nomreq.session.passport.user
Anubhav
@AB J'ai écrit du code pour trouver l'utilisateur à partir de l'ID qui a été transmis pour désérialiser la méthode comme premier paramètre. Mais dans chaque demande, il récupère l'utilisateur de db. Cela entraîne une perte de performances pour db. Que dois-je écrire d'autre pour désérialiser la fonction pour vérifier si elle existe ou non en session?
uzay95
2
@AB Je ne comprends pas ce que vous avez suggéré à uzay95. Donc, dans ma session, je n'ai que user._id. Mais à chaque demande, je dois utiliser cet identifiant pour désérialiser de la base de données aka findUserByID et cela le mettra dans req.user. Comment éviter de faire un tel appel à chaque demande?
Zanko
10
@Zanko Vous pouvez mettre l'intégralité de l'objet utilisateur dans les données de session, mais ce n'est généralement pas une bonne idée car cela peut avoir d'autres effets secondaires. Par exemple, lorsque l'utilisateur met à jour son nom d'utilisateur, vous devez également mettre à jour les données de session, sinon vous obtiendrez des tickets en raison de "la fonction de renommage rompue". C'est un exemple relativement inoffensif. La même chose pourrait arriver avec des bits d'autorisation ou des données sensibles égales (Oups ...). Essentiellement les mêmes problèmes que vous rencontrez toujours si vous avez des données en double. TL; DR - Ne le faites pas.
Max Truxa du
1
Si je ne me trompe pas, la req.session.passport.user = {id: '..'}partie du diagramme est légèrement décalée et devrait req.session.passport.user = 785352plutôt être où elle 785352est user.id. J'ai du mal à me connecter à la console pour le prouver, mais il semble que cela aurait du sens. Lorsque vous appelez done(null, user.id);, il serait logique de prendre le deuxième argument - user.iddans ce cas - et de l'assigner à req.session.passport.user, au lieu de l'assigner à req.session.passport.user.id. Et si vous passiez à la place user? req.sesssion.passport.user.id = usern'aurait pas de sens.
Adam Zerner
21

Pour toute personne utilisant Koa et koa-passeport :

Sachez que la clé de l'utilisateur définie dans la méthode serializeUser (souvent un identifiant unique pour cet utilisateur) sera stockée dans:

this.session.passport.user

Lorsque vous définissez dans done(null, user)deserializeUser où «utilisateur» est un objet utilisateur de votre base de données:

this.req.user OU this.passport.user

pour une raison quelconque, le this.usercontexte Koa n'est jamais défini lorsque vous appelez done (null, user) dans votre méthode deserializeUser.

Vous pouvez donc écrire votre propre middleware après l'appel à app.use (passport.session ()) pour le mettre dans this.user comme ceci:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

Si vous ne savez pas comment fonctionnent serializeUser et deserializeUser, contactez-moi sur Twitter. @yvanscher

yvanscher
la source
Désolé pour le nécropostage ici, mais j'ai un problème maintenant après avoir lu l'explication de désérialisation. J'ai posté une question à ce sujet ici sur SO: stackoverflow.com/questions/54154047/…
Peter Kellner
Super utile, mais a toujours des problèmes pour lire l'utilisateur à partir d'autres itinéraires. Est-ce que quelqu'un pourrait m'aider? stackoverflow.com/questions/60709882/…
Harry Lincoln