你如何向外行解释Passport的序列化和反序列化方法的工作流程?

Where does user.id go after passport.serializeUser has been called? We are calling passport.deserializeUser right after it where does it fit in the workflow? // 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); }); });

我还没想明白呢。我有一个完整的工作应用程序,没有遇到任何类型的错误。

我只是想知道这里到底发生了什么?

任何帮助都是感激的。


当前回答

基本上,我们只是使用序列化器将user-id存储在会话中,当我们需要用户模型实例时,我们使用user-id在数据库中搜索,这是使用反序列化器完成的。

只要会话是活动的,并且用户通过了身份验证,

req.session.passport.user

将始终对应于用户模型实例。

如果我们不将user-id保存到会话中,如果有重定向,我们将无法知道用户是否已经过身份验证。

一旦用户通过身份验证,就会设置req.session.passport.user。 因此,所有未来的请求都将知道用户已经过身份验证。

希望这能简化。

其他回答

对于任何使用可可豆和可可豆护照的人:

要知道serializeUser方法中设置的用户的键(通常是该用户的唯一id)将存储在:

this.session.passport.user

当你在deserializeUser中设置done(null, user)时,其中“user”是数据库中的某个用户对象:

this.req.user 或 this.passport.user

出于某种原因。在您的deserializeUser方法中调用done(null, user)时,用户Koa上下文永远不会被设置。

所以你可以在调用app.use(passport.session())之后编写自己的中间件,把它放在这里。用户如下:

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

如果您不清楚serializeUser和deserializeUser是如何工作的,请在twitter上联系我。@yvanscher

用户在哪里。我去拿护照。serializeUser是否被调用?

用户id(作为done函数的第二个参数提供)保存在会话中,稍后用于通过deserializeUser函数检索整个对象。

serializeUser决定会话中应该存储用户对象的哪些数据。serializeUser方法的结果作为req.session.passport.user ={}附加到会话。例如,在这里,它将是(因为我们提供用户id作为键)req.session.passport.user = {id: 'xyz'}

我们在它后面调用passport。deserializeuser它在工作流中的位置是什么?

deserializeUser的第一个参数对应给done函数的user对象的键(见1.)。你的整个对象都是在这个键的帮助下被检索的。这里的键是用户id(键可以是用户对象的任何键,例如名称,电子邮件等)。 在deserializeUser中,该键与内存中的数组/数据库或任何数据资源匹配。

获取的对象作为req.user附加到请求对象

视觉流

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

所以我在这个问题上卡住了很长一段时间,所以我做了一个快速的设置文件,这样就不会有人再被这个垃圾卡住了

passportmgmt.js

const localStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const User = require('./db-schemas/models').UserModel;
/*^^^^^^^^^^^ delete above import and modify below definition as needed 
const mongoose = require('mongoose')
mongoose.connect("mongodb://localhost:27017/database_name");

const UserSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true
    }
});
const UserModel = mongoose.model('collection_name', UserSchema);
^^^^^^^^^^^^^^^ Change UserModel to User */
const passport = require('passport');

function passportSetupUwU(app) {
    const cookieParser = require('cookie-parser');
    const session = require('express-session');
    const MongoDBStore = require('connect-mongodb-session')(session);

    app.use(cookieParser());
    app.set('trust proxy', 1);
    app.use(session({
    secret: "secret",
    resave: false,
    saveUninitialized: false,
    store: new MongoDBStore({
        uri: "mongodb://localhost:27017/database_name",
        collection: "collection_name"
    })
    }));

    // Passport.js
    app.use(passport.initialize());
    app.use(passport.session());
}

passport.serializeUser(function(user, cb) {
    console.log("serializing user uwu:" + JSON.stringify(user))
    process.nextTick(function() {
        return cb(null, user.id)
    })
})

passport.deserializeUser(function (id, cb) {
    console.log("deserializing user owo:" + JSON.stringify(id))
    User.findOne({id:id}, function (err, user) {
        if (err) { return cb(err)}
        return cb(null, user);
    })
});

passport.use(new localStrategy(function (username, password, done) {
    console.log("attempted login with %s:%s", username, password);
    User.findOne({ username: username }, function (err, user) {
        if (err) return done(err);
        if (!user) return done(null, false, { message: 'No such user exists.' });

        bcrypt.compare(password, user.password, function (err, res) {
            if (err) return done(err);
            if (res === false) return done(null, false, { message: 'Incorrect password.' });
            
            return done(null, user);
        });
    });
}));

module.exports = {setup: passportSetupUwU}

现在只需导入并在app.js中运行passportSetupUwU函数,你就可以开始了:

app.js exerpt

// some example middleware and stuff i happened to have
const PPSetup = require('./passportmgmt').setup
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

//
// <- PUT IT LIKE HERE OR SOMETHING
//
PPSetup(app);

// some example routes and api endpoints i happened to have
app.use('/api/', apiRouter);
apiRouter.use('/', indexRouter);
apiRouter.use('/users', usersRouter);

apiRouter.post('/login', passport.authenticate('local', {

你可以用这个代码升级旧的序列化和反序列化,请在这个帖子上找到新的解决方案。

        passport.serializeUser(function(user, cb) {
          process.nextTick(function() {
            cb(null, { id: user.id, username: user.username });
          });
        });
        
        passport.deserializeUser(function(user, cb) {
          process.nextTick(function() {
            return cb(null, user);
          });
        });

基本上,我们只是使用序列化器将user-id存储在会话中,当我们需要用户模型实例时,我们使用user-id在数据库中搜索,这是使用反序列化器完成的。

只要会话是活动的,并且用户通过了身份验证,

req.session.passport.user

将始终对应于用户模型实例。

如果我们不将user-id保存到会话中,如果有重定向,我们将无法知道用户是否已经过身份验证。

一旦用户通过身份验证,就会设置req.session.passport.user。 因此,所有未来的请求都将知道用户已经过身份验证。

希望这能简化。