Comprendere il passaporto serializzare deserializzare


337

Come spiegheresti il ​​flusso di lavoro dei metodi di serializzazione e deserializzazione di Passport a un laico.

  1. Dove user.idva dopo che passport.serializeUserè stato chiamato?

  2. Lo stiamo chiamando passport.deserializeUsersubito dopo dove si adatta al flusso di lavoro?

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

Sto ancora cercando di avvolgerci la testa. Ho un'app funzionante completa e non sto riscontrando errori di alcun tipo.

Volevo solo capire cosa sta succedendo esattamente qui?

Qualsiasi aiuto è apprezzato.

Risposte:


452
  1. Dove user.idva dopo che passport.serializeUserè stato chiamato?

L'ID utente (fornito come secondo argomento della donefunzione) viene salvato nella sessione e viene successivamente utilizzato per recuperare l'intero oggetto tramite la deserializeUserfunzione.

serializeUserdetermina quali dati dell'oggetto utente devono essere archiviati nella sessione. Il risultato del metodo serializeUser è allegato alla sessione come req.session.passport.user = {}. Qui per esempio, sarebbe (dato che forniamo l'id utente come chiave)req.session.passport.user = {id: 'xyz'}

  1. Lo stiamo chiamando passport.deserializeUsersubito dopo dove si adatta al flusso di lavoro?

Il primo argomento di deserializeUsercorrisponde alla chiave dell'oggetto utente che è stato dato alla donefunzione (vedi 1.). Quindi l'intero oggetto viene recuperato con l'aiuto di quella chiave. Quella chiave qui è l'id utente (chiave può essere qualsiasi chiave dell'oggetto utente, ad esempio nome, e-mail, ecc.). In deserializeUserquella chiave è abbinato l'array / database in memoria o qualsiasi risorsa di dati.

L'oggetto recuperato è collegato all'oggetto richiesta come req.user

Flusso visivo

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

2
Quindi viene user.idsalvato come req.session.passport.usero viene usermemorizzato comereq.session.passport.user
Anubhav il

@AB Ho scritto il codice per trovare l'utente dall'ID che è stato passato per deserializzare il metodo come primo parametro. Ma in ogni richiesta recupera l'utente da db. Ciò comporta una perdita di prestazioni per db. Cos'altro dovrei scrivere per deserializzare la funzione per verificare se esiste o meno nella sessione?
uzay95,

2
@AB Non capisco cosa mi hai suggerito di uzay95. Quindi nella mia sessione ho solo user._id. Ma su ogni richiesta, devo usare quell'id per deserializzare dal database aka findUserByID e questo lo metterà in req.user. Come posso evitare di effettuare tale chiamata su ogni richiesta?
Zanko,

10
@Zanko Potresti inserire l'intero oggetto utente nei dati della sessione, ma di solito non è una buona idea perché può avere altri effetti collaterali. Ad esempio, quando l'utente aggiorna il proprio nome utente, è necessario aggiornare anche i dati della sessione, altrimenti si otterranno i biglietti a causa della "funzionalità di ridenominazione interrotta". Questo è un esempio relativamente innocuo. Lo stesso potrebbe accadere con bit di autorizzazione o dati sensibili uguali (Oops ...). Essenzialmente gli stessi problemi che si verificano sempre se si hanno dati duplicati. TL; DR - Non farlo.
Max Truxa,

1
Se non mi sbaglio, la req.session.passport.user = {id: '..'}parte del diagramma è leggermente fuori, e dovrebbe essere req.session.passport.user = 785352, invece, dove 785352è user.id. Ho problemi con la registrazione della console per dimostrarlo, ma sembra che avrebbe senso. Quando chiami done(null, user.id);, avrebbe senso prendere il secondo argomento - user.idin questo caso - e assegnarlo a req.session.passport.user, invece di assegnarlo a req.session.passport.user.id. Perché se invece passassi user? req.sesssion.passport.user.id = usernon avrebbe senso.
Adam Zerner

21

Per chiunque utilizzi Koa e koa-passport :

Sappi che la chiave per l'utente impostata nel metodo serializeUser (spesso un ID univoco per quell'utente) verrà archiviata in:

this.session.passport.user

Quando si imposta in done(null, user)deserializeUser dove "user" è un oggetto utente dal database:

this.req.user O this.passport.user

per qualche motivo il this.usercontesto Koa non viene mai impostato quando chiami done (null, user) nel tuo metodo deserializeUser.

Quindi puoi scrivere il tuo middleware dopo la chiamata a app.use (passport.session ()) per inserirlo in this.user in questo modo:

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

Se non sei chiaro su come funzionano serializeUser e deserializeUser, contattami su Twitter. @yvanscher


Ci scusiamo per il necropostaggio qui, ma ora ho una preoccupazione dopo aver letto la spiegazione deserializzata. Ho pubblicato una domanda al riguardo qui su SO: stackoverflow.com/questions/54154047/…
Peter Kellner,

Super utile, ma continuando ad avere problemi con la lettura dell'utente da altre rotte. Qualcuno può aiutarmi qui? stackoverflow.com/questions/60709882/…
Harry Lincoln,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.