Entender el pasaporte serializar deserializar

337

¿Cómo explicarías el flujo de trabajo de los métodos de serialización y deserialización de Passport a un laico?

  1. ¿A dónde user.idva después de passport.serializeUserhaber sido llamado?

  2. Estamos llamando passport.deserializeUserjusto después de eso, ¿dónde encaja en el flujo de trabajo?

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

Todavía estoy tratando de entenderlo. Tengo una aplicación de trabajo completa y no me encuentro con errores de ningún tipo.

Solo quería entender qué está pasando exactamente aquí.

Cualquier ayuda es apreciada.

Anubhav
fuente

Respuestas:

452
  1. ¿A dónde user.idva después de passport.serializeUserhaber sido llamado?

El ID de usuario (que proporciona como segundo argumento de la donefunción) se guarda en la sesión y luego se utiliza para recuperar el objeto completo a través de la deserializeUserfunción.

serializeUserdetermina qué datos del objeto de usuario deben almacenarse en la sesión. El resultado del método serializeUser se adjunta a la sesión como req.session.passport.user = {}. Aquí, por ejemplo, sería (ya que proporcionamos la identificación del usuario como clave)req.session.passport.user = {id: 'xyz'}

  1. Estamos llamando passport.deserializeUserjusto después de eso, ¿dónde encaja en el flujo de trabajo?

El primer argumento de deserializeUsercorresponde a la clave del objeto de usuario que se le dio a la donefunción (ver 1.). Entonces todo su objeto se recupera con la ayuda de esa clave. Esa clave aquí es la identificación de usuario (la clave puede ser cualquier clave del objeto de usuario, es decir, nombre, correo electrónico, etc.). En deserializeUseresa clave se corresponde con la matriz / base de datos en memoria o cualquier recurso de datos.

El objeto obtenido se adjunta al objeto de solicitud como req.user

Flujo visual

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   
});
AB
fuente
2
Por lo tanto, se user.idguarda como req.session.passport.usero se useralmacena comoreq.session.passport.user
Anubhav
@AB Escribí un código para encontrar al usuario desde la identificación que se pasó para deserializar el método como primer parámetro. Pero en cada solicitud está recuperando usuarios de db. Esto hace que la pérdida de rendimiento para db. ¿Qué más debo escribir para deserializar la función para verificar si existe en la sesión o no?
uzay95
2
@AB No entiendo lo que le sugirió a uzay95. Entonces, en mi sesión solo tengo user._id. Pero en cada solicitud, tengo que usar esa identificación para deserializarla de la base de datos, también conocida como findUserByID, y eso la colocará en req.user. ¿Cómo evito hacer tal llamada en cada solicitud?
Zanko
10
@Zanko Podría poner todo el objeto de usuario en los datos de la sesión, pero eso generalmente no es una buena idea porque puede tener otros efectos secundarios. Por ejemplo, cuando el usuario actualiza su nombre de usuario, también debe actualizar los datos de la sesión; de lo contrario, obtendrá tickets debido a "la función de cambio de nombre". Ese es un ejemplo relativamente inofensivo. Lo mismo podría suceder con bits de permiso o datos confidenciales iguales (Uy ...). Esencialmente, los mismos problemas con los que siempre se encuentra si tiene datos duplicados. TL; DR - No lo hagas.
Max Truxa
1
Si no me equivoco, la req.session.passport.user = {id: '..'}parte del diagrama está ligeramente apagada, y debería estar req.session.passport.user = 785352en su lugar, donde 785352está user.id. Tengo problemas para iniciar sesión en la consola para probarlo, pero parece que tendría sentido. Cuando llame done(null, user.id);, tendría sentido tomar el segundo argumento, user.iden este caso, y asignarlo a req.session.passport.user, en lugar de asignarlo a req.session.passport.user.id. Porque, ¿qué pasa si en su lugar pasas user? req.sesssion.passport.user.id = userNo tendría sentido.
Adam Zerner
21

Para cualquiera que use Koa y el pasaporte koa :

Sepa que la clave para el usuario establecida en el método serializeUser (a menudo una identificación única para ese usuario) se almacenará en:

this.session.passport.user

Cuando se establece en done(null, user)deserializeUser donde 'user' es algún objeto de usuario de su base de datos:

this.req.user O this.passport.user

por alguna razón, el this.usercontexto de Koa nunca se establece cuando llamas a done (null, user) en tu método deserializeUser.

Para que pueda escribir su propio middleware después de la llamada a app.use (passport.session ()) para ponerlo en this.user así:

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

Si no tienes claro cómo funcionan serializeUser y deserializeUser, solo contáctame en Twitter. @yvanscher

yvanscher
fuente
Perdón por la necroposición aquí, pero ahora tengo una preocupación después de leer la explicación de deserialización. He publicado una pregunta sobre esto aquí en SO: stackoverflow.com/questions/54154047/…
Peter Kellner
Súper útil, pero aún tiene algunos problemas para leer al usuario desde otras rutas. ¿Puede alguien ayudarme aquí? stackoverflow.com/questions/60709882/…
Harry Lincoln