Passport.js - Kesalahan: gagal membuat serialisasi pengguna menjadi sesi

179

Saya mendapat masalah dengan modul Passport.js dan Express.js.

Ini adalah kode saya dan saya hanya ingin menggunakan login dengan hardcode untuk percobaan pertama.

Saya selalu menerima pesan:

Saya mencari banyak dan menemukan beberapa posting di stackoverflow tetapi saya tidak mendapatkan kegagalan.

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

Kode saya terlihat seperti ini.

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

}();

Terima kasih.

pengguna2244925
sumber

Jawaban:

362

Sepertinya Anda tidak menerapkan passport.serializeUserdan passport.deserializeUser. Coba tambahkan ini:

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

passport.deserializeUser(function(user, done) {
  done(null, user);
});
robertklep
sumber
2
Bekerja untukku. Mengapa saya tidak harus menggunakan bagian 'id' seperti yang ditulis di tempat lain?
schlenger
9
@schlenger akan tergantung pada bagaimana Anda menerapkan serialisasi. Terkadang Anda membuat serial berdasarkan id pengguna, yang berarti bahwa serializeUserfungsi menyimpan hanya id pengguna di sesi, dan deserializeUsermenggunakan id itu untuk mengambil data pengguna dari database (misalnya). Ini untuk mencegah penyimpanan sesi berisi data pengguna aktual itu sendiri.
robertklep
+1 @robertklep komentar. Saya selalu menghindari serialisasi informasi pengguna tetapi hanya id (untuk alasan bloat / perf secara pribadi).
electblake
2
@robertklep Saya tidak ingin menyimpannya di sesi. Saya menggunakan JWT. Apakah serializeUser / deserializeUser diperlukan? Saya ingin sesi tidak. Saya menggunakan JWT
Internial
@Internial tidak yakin jika Anda membutuhkannya, tetapi itu akan menjadi hal yang mudah untuk diuji.
robertklep
44

Jika Anda memutuskan untuk tidak menggunakan sesi, Anda dapat mengatur sesi menjadi false

app.post('/login', passport.authenticate('local', {
  successRedirect: '/accessed',
  failureRedirect: '/access',
  session: false
}));
Kevin
sumber
Tapi itu tidak akan mematikan sesi pada semua titik akhir lainnya (di mana saya juga tidak ingin sesi apa pun)
jayarjo
17

Kedengarannya seperti Anda melewatkan bagian dari pengaturan paspor, khususnya dua metode ini:

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

Saya menambahkan sedikit tentang ._idvs. .idtetapi cuplikan ini dari Bagian Konfigurasi dokumen, berikan yang lain baca dan semoga berhasil :)

electblake
sumber
2

Di sini cara yang bekerja tetapi masih malas untuk menggunakan sesi dan masih "membuat serialisasi" nilai-nilai.

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

dalam kasus atau kesalahan aneh tanyakan pada diri sendiri: "Apakah saya hanya mengatur '_id' di objek pengguna saya?" - dalam kebanyakan kasus Anda tidak. Jadi gunakan atribut yang tepat sebagai kunci.

Ganku Caelestis
sumber
0

Menggunakan Promise dengan serializeUser & 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}`);
    });
});

Silakan lihat repo github saya untuk contoh kode lengkap bagaimana mengatasi masalah ini.

Isak La Fleur
sumber
-1

di passport.use ('local-login' ...) / atau / ('local-singup' ...)

jika err Anda harus mengembalikan "false" err {return done (null, req.flash ('megsign', 'Nama pengguna sudah ada #! #'));} true {return done (null, false, req.flash (' megsign ',' Nama pengguna sudah ada #! # '));}

annguyen
sumber