Passport.js - Erreur: échec de la sérialisation de l'utilisateur dans la session

180

J'ai un problème avec le module Passport.js et Express.js.

Ceci est mon code et je veux juste utiliser une connexion codée en dur pour le premier essai.

Je reçois toujours le message:

J'ai beaucoup cherché et trouvé des articles dans stackoverflow mais je n'ai pas eu l'échec.

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

Mon code ressemble à ceci.

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

}();

Merci.

user2244925
la source

Réponses:

363

Il semble que vous n'ayez pas implémenté passport.serializeUseret passport.deserializeUser. Essayez d'ajouter ceci:

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

passport.deserializeUser(function(user, done) {
  done(null, user);
});
robertklep
la source
2
A travaillé pour moi. Pourquoi n'ai-je pas à utiliser la partie «id» comme écrite partout ailleurs?
schlenger
9
@schlenger cela dépendrait de la façon dont vous implémentez la sérialisation. Parfois, vous sérialisez par ID utilisateur, ce qui signifie que la serializeUserfonction stocke uniquement l'ID utilisateur dans la session et deserializeUserutilise cet ID pour récupérer les données utilisateur à partir d'une base de données (par exemple). Cela évite que le stockage de session ne contienne les données utilisateur réelles.
robertklep
+1 @robertklep commentaire. J'éviterais toujours de sérialiser les informations utilisateur mais uniquement les identifiants (pour des raisons de ballonnement / perf personnellement).
electblake
2
@robertklep Je ne veux pas le stocker en session. J'utilise JWT. SerializeUser / deserializeUser est-il requis? Je veux une session non. J'utilise JWT
Internial
@Internial ne sait pas si vous en avez besoin, mais ce serait une chose facile à tester.
robertklep
44

Si vous décidez de ne pas utiliser de sessions, vous pouvez définir la session sur false

app.post('/login', passport.authenticate('local', {
  successRedirect: '/accessed',
  failureRedirect: '/access',
  session: false
}));
Kevin
la source
Mais cela ne désactivera pas la session sur tous les autres points de terminaison (où je ne veux pas non plus de session)
jayarjo
17

On dirait que vous avez manqué une partie de la configuration de passeportjs, en particulier ces deux méthodes:

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

J'ai ajouté le mot sur ._idvs, .idmais cet extrait de code provient de la section Configurer de la documentation, donnez-en une autre lecture et bonne chance :)

electblake
la source
2

Voici une manière fonctionnelle mais toujours paresseuse d'utiliser les sessions tout en «sérialisant» les valeurs.

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

en cas d'erreurs étranges, demandez-vous simplement: "Dois-je définir '_id' dans mon objet utilisateur?" - dans la plupart des cas, vous ne le faites pas. Utilisez donc un attribut approprié comme clé.

Ganku Caelestis
la source
0

Utilisation de Promise avec serializeUser et 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}`);
    });
});

Veuillez consulter mon dépôt github pour un exemple de code complet sur la façon de résoudre ce problème.

Isak La Fleur
la source
-1

dans passeport.use ('local-login' ...) / ou / ('local-singup' ...)

si err vous devez retourner "false" err {return done (null, req.flash ('megsign', 'Le nom d'utilisateur existe déjà #! #'));} true {return done (null, false, req.flash (' megsign ',' Le nom d'utilisateur existe déjà #! # '));}

Annguyen
la source