Noções básicas sobre serialização de passaporte desserializar

337

Como você explicaria o fluxo de trabalho dos métodos de serialização e desserialização do Passport para um leigo.

  1. Para onde user.idvai depois passport.serializeUserfoi chamado?

  2. Estamos ligando passport.deserializeUserlogo depois para onde ele se encaixa no fluxo de trabalho?

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

Eu ainda estou tentando envolver minha cabeça em torno disso. Eu tenho um aplicativo de trabalho completo e não estou encontrando erros de qualquer tipo.

Eu só queria entender o que exatamente está acontecendo aqui?

Qualquer ajuda é apreciada.

Anubhav
fonte

Respostas:

451
  1. Para onde user.idvai depois passport.serializeUserfoi chamado?

O ID do usuário (fornecido como o segundo argumento da donefunção) é salvo na sessão e mais tarde é usado para recuperar o objeto inteiro por meio da deserializeUserfunção.

serializeUserdetermina quais dados do objeto de usuário devem ser armazenados na sessão. O resultado do método serializeUser é anexado à sessão como req.session.passport.user = {}. Aqui, por exemplo, seria (como fornecemos o ID do usuário como a chave)req.session.passport.user = {id: 'xyz'}

  1. Estamos ligando passport.deserializeUserlogo depois para onde ele se encaixa no fluxo de trabalho?

O primeiro argumento de deserializeUsercorresponde à chave do objeto de usuário que foi dada à donefunção (consulte 1.). Portanto, todo o seu objeto é recuperado com a ajuda dessa chave. Essa chave aqui é a identificação do usuário (a chave pode ser qualquer chave do objeto do usuário, por exemplo, nome, email etc.). Nessa deserializeUserchave é correspondida a matriz / banco de dados na memória ou qualquer recurso de dados.

O objeto buscado é anexado ao objeto de solicitação como req.user

Fluxo 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
fonte
2
Então é user.idsalvo como req.session.passport.userou é userem si armazenado comoreq.session.passport.user
Anubhav
@AB Escrevi o código para encontrar o usuário a partir do ID que foi passado para desserializar o método como primeiro parâmetro. Mas em cada solicitação, ele está recuperando o usuário do db. Isso causa perda de desempenho para o banco de dados. O que mais devo escrever para desserializar a função para verificar se ela existe ou não na sessão?
Uzay95
2
@ AB Eu não entendo o que você sugeriu para uzay95. Então, na minha sessão, tenho apenas user._id. Mas em cada solicitação, eu tenho que usar esse ID para desserializar do banco de dados, também conhecido como findUserByID, e isso o colocará em req.user. Como evito fazer essa ligação em cada solicitação?
Zanko 21/07
10
@ Zanko Você pode colocar todo o objeto do usuário nos dados da sessão, mas isso geralmente não é uma boa ideia, pois pode ter outros efeitos colaterais. Por exemplo, quando o usuário atualiza seu nome de usuário, você também precisa atualizar os dados da sessão, caso contrário, você receberá tickets por causa do "recurso de renomeação quebrada". Esse é um exemplo relativamente inofensivo. O mesmo poderia acontecer com os bits de permissão ou com dados confidenciais iguais (Opa ...). Essencialmente, os mesmos problemas que você sempre encontra se tiver dados duplicados. TL; DR - Não faça isso.
Max Truxa 22/08/16
11
Se não me engano, a req.session.passport.user = {id: '..'}parte do diagrama está ligeiramente desligada e req.session.passport.user = 785352, em vez disso, deve estar onde 785352está user.id. Estou tendo problemas para fazer logon no console para provar isso, mas parece que faria sentido. Quando você telefona done(null, user.id);, faria sentido usar o segundo argumento - user.idnesse caso - e atribuí-lo a req.session.passport.user, em vez de atribuí-lo req.session.passport.user.id. Porque e se você passar em vez disso user? req.sesssion.passport.user.id = usernão faria sentido.
Adam Zerner
21

Para quem usa o Koa e o passaporte koa :

Saiba que a chave do usuário definida no método serializeUser (geralmente um ID exclusivo para esse usuário) será armazenada em:

this.session.passport.user

Quando você define done(null, user)deserializeUser, em que 'user' é um objeto de usuário do seu banco de dados:

this.req.user OU this.passport.user

por algum motivo, o this.usercontexto Koa nunca é definido quando você conclui (nulo, usuário) no seu método deserializeUser.

Portanto, você pode escrever seu próprio middleware após a chamada para app.use (passport.session ()) para colocá-lo neste this.user da seguinte maneira:

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

Se você não sabe ao certo como o serializeUser e o desserializeUser funcionam, basta acessar o twitter. @yvanscher

yvanscher
fonte
Desculpe por fazer necropost aqui, mas agora tenho uma preocupação depois de ler a explicação sobre desserialização. Eu postei uma pergunta sobre isso aqui no SO: stackoverflow.com/questions/54154047/...
Peter Kellner
Super útil, mas ainda tendo problemas ao ler o usuário de outras rotas. Alguém pode me ajudar aqui? stackoverflow.com/questions/60709882/…
Harry Lincoln