Passport.js - Erro: falha ao serializar o usuário na sessão

179

Eu tive um problema com o módulo Passport.js e o Express.js.

Este é o meu código e eu só quero usar um login codificado na primeira tentativa.

Eu sempre recebo a mensagem:

Pesquisei bastante e encontrei algumas postagens no stackoverflow, mas não obtive a falha.

Error: failed to serialize user into session
    at pass (c:\Development\private\aortmann\bootstrap_blog\node_modules\passport\lib\passport\index.js:275:19)

Meu código fica assim.

'use strict';

var express = require('express');
var path = require('path');
var fs = require('fs');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var nodemailer = require('nodemailer');

var app = express();

module.exports = function setupBlog(mailTransport, database){
var config = JSON.parse(fs.readFileSync('./blog.config'));

app.set('view options', {layout: false});

app.use(express.static(path.join(__dirname, '../', 'resources', 'html')));


app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'secret' }));
app.use(passport.initialize());
app.use(passport.session());


app.get('/blog/:blogTitle', function(req, res) {
  var blogTitle = req.params.blogTitle;
  if(blogTitle === 'newest'){
    database.getLatestBlogPost(function(post) {
      res.send(post);
    });
  } else {
    database.getBlogPostByTitle(blogTitle, function(blogPost) {
      res.send(blogPost);
    });
  }
});

passport.use(new LocalStrategy(function(username, password, done) {
  // database.login(username, password, done);
  if (username === 'admin' && password === 'admin') {
    console.log('in');
    done(null, { username: username });
  } else {
    done(null, false);
  }
}));

app.post('/login', passport.authenticate('local', {
  successRedirect: '/accessed',
  failureRedirect: '/access'
}));





app.listen(8080);
console.log('Blog is running on port 8080');

}();

Obrigado.

user2244925
fonte

Respostas:

362

Parece que você não implementou passport.serializeUsere passport.deserializeUser. Tente adicionar isto:

passport.serializeUser(function(user, done) {
  done(null, user);
});

passport.deserializeUser(function(user, done) {
  done(null, user);
});
robertklep
fonte
2
Trabalhou para mim. Por que não preciso usar a parte 'id' como escrita em qualquer outro lugar?
Schlenger
9
@ schlenger, depende de como você implementa a serialização. Às vezes, você serializa pelo ID do usuário, o que significa que a serializeUserfunção armazena apenas o ID do usuário na sessão e deserializeUserusa esse ID para recuperar os dados do usuário de um banco de dados (por exemplo). Isso evita que o armazenamento da sessão contenha os dados reais do usuário.
robertklep
Marcar um comentário com @robertklep. Eu sempre evitava serializar as informações do usuário, mas apenas os IDs (por razões de inchaço / perf pessoalmente).
Electblake
2
@robertklep Não quero armazená-lo em sessão. Estou usando o JWT. SerializeUser / deserializeUser é necessário? Eu quero uma sessão sem. Eu estou usando JWT
Internial 30/10
@ International não tem certeza se você precisa deles, mas seria uma coisa fácil de testar.
Robertklep
44

Se você decidir não usar sessões, poderá definir a sessão como false

app.post('/login', passport.authenticate('local', {
  successRedirect: '/accessed',
  failureRedirect: '/access',
  session: false
}));
Kevin
fonte
Mas isso não vai desligar sessão em todos os outros pontos de extremidade (onde eu também não quero qualquer sessão)
jayarjo
17

Parece que você perdeu uma parte da configuração do passportjs, especificamente esses dois métodos:

passport.serializeUser(function(user, done) {
    done(null, user._id);
    // if you use Model.id as your idAttribute maybe you'd want
    // done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});

Eu adicionei um pouco sobre ._idvs., .idmas esse trecho é da seção de configuração dos documentos, faça outra leitura e boa sorte :)

electblake
fonte
2

Aqui, uma maneira prática, mas ainda preguiçosa, de usar sessões e ainda "serializar" os valores.

var user_cache = {};

passport.serializeUser(function(user, next) {
  let id = user._id;
  user_cache[id] = user;
  next(null, id);
});

passport.deserializeUser(function(id, next) {
  next(null, user_cache[id]);
});

no caso de erros estranhos, pergunte a si mesmo: "Eu realmente defino '_id' no meu objeto de usuário?" - na maioria dos casos você não. Portanto, use um atributo apropriado como chave.

Ganku Caelestis
fonte
0

Usando o Promise com serializeUser e deserializeUser:

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  // console.log(`id: ${id}`);
  User.findById(id)
    .then((user) => {
      done(null, user);
    })
    .catch((error) => {
      console.log(`Error: ${error}`);
    });
});

Consulte meu repositório do github para obter um exemplo de código completo de como resolver esse problema.

Isak La Fleur
fonte
-1

no passport.use ('local-login' ...) / ou / ('local-singup' ...)

se err você tem que retornar "false" err {return done (null, req.flash ('megsign', 'Nome de usuário já existe #! #'));} true {return done (null, false, req.flash (' megsign ',' Nome de usuário já existe #! # '));}

annguyen
fonte