我是否实现序列化和反序列化 NodesJS + Passport + RedisStore



我是否实现序列化和反序列化?

RedisStore 被设置为我在 Express 上的会话存储。这是否意味着我不实现序列化和反序列化?它会自动发生吗?

当我不实现这些方法时,我收到以下快速错误 - 500 错误:无法将用户序列化到会话中。当我实现它们时,我不确定在反序列化中放入什么。

下面的代码似乎有效,但会话没有持久化。每次访问该网站时,我都需要登录。

有没有NodeJS + Passport + RedisStore的好例子?

var sessionStore = new RedisStore({
                                        host: rtg.hostname,
                                        port: rtg.port,
                                        db: redisAuth[0],
                                        pass: redisAuth[1]
                                      });
passport.use(new ForceDotComStrategy({
    clientID: clientId,
    clientSecret: clientSecret,
    callbackURL: myurl
},
function(token, tokenSecret, profile, done) {
    console.log(profile);
    return done(null, profile);
  }
));
appSecure.configure('production', function(){
appSecure.use(allowCrossDomain);
appSecure.use(express.cookieParser(expressSecret));
appSecure.use(express.bodyParser());
appSecure.use(express.methodOverride());
appSecure.set('port', port); 
appSecure.use(express.session({ secret: expressSecret, store: sessionStore, key:'expressSid', cookie: { maxAge : 604800, domain:'.domain.com'}})); 
appSecure.use(passport.initialize());
appSecure.use(passport.session());
appSecure.use(appSecure.router);
appSecure.use(express.static(__dirname + '/public'));
appSecure.use(express.errorHandler());
});
passport.serializeUser(function( user, done ) {
    done( null, user.id);
});
passport.deserializeUser(function( user, done ) {
    done( null, user );
});

如果您正在使用会话,则必须提供具有序列化和反序列化功能的护照。将 Redis 实现为会话存储与 passport 的实现方式无关,它只处理会话数据的存储位置。

使用护照实施会话

正如我所说,序列化和反序列化函数必须提供给护照才能使会话正常工作。

序列化函数的目的是返回足够的标识信息,以便在任何后续请求中恢复用户帐户。具体来说,done()方法的第二个参数是序列化到会话数据中的信息

您提供的序列化函数旨在根据序列化到会话的标识信息返回用户配置文件

以下是讨论会议部分中护照指南中的示例:

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

在上面的示例中,passport.serializeUser()提供了一个函数,该函数采用两个参数,即用户配置文件(user(和回调函数(done(。回调函数将识别信息(user.id,但如果您使用的是mongoDB,则可能需要user._id从数据库中恢复帐户所需的识别信息作为第二个参数。这将在每个经过身份验证的请求上调用,并将识别信息存储在会话数据中(无论是在 cookie 中还是在您的 Redis 存储中(。

passport.deserializeUser()提供了一个函数,该函数也接受两个参数,识别信息(id(和回调函数(done(。标识信息是在上一个请求 (user.id ( 中序列化为会话数据的内容。此处的回调函数需要用户配置文件作为第二个参数,或者在检索配置文件时引发的任何错误作为第一个参数。User.findById()函数是数据库中用户配置文件的查找函数。在此示例中User对象是具有findById()函数的猫鼬模型的实例。

提供给passport.deserializeUser()的函数由护照中间件调用,passport.session()路由处理之前存储用户配置文件(user(以req.user

将 Redis 实现为会话存储

使用 Redis 的目的是存储会话数据

服务器端,因此客户端存储的唯一数据是会话 ID。同样,这与你实现 passport 的方式无关,只要你向应用添加了会话支持,passport 就不关心会话数据的存储位置。这个关于堆栈溢出的上一个问题解决了如何实现 Redis 的问题

有点晚了,但我已经让这个视觉的东西来理解

  1. 何时以及如何调用策略/本地/Facebook/etc,以及如何调用req.login或passport.serializeUser((以及done((是什么?

passport.authenticate()调用您作为参数提供的相应策略,您将req.body.passwordreq.body.username与存储的数据库或内存中存储的密码和用户名进行匹配。 如果用户找到,则将其作为第二个参数传递给done(),否则return false

完成的回调返回到passport.authenticate() 。 如果之前使用用户调用 DONE(即done(null,user); (,则req,logIn()自动调用或由后台用户调用

req.logIn()呼叫passport.serializeUser()

  1. 什么是 passport.serializeUser,调用此函数后user.some_key去哪里?

您在序列化函数的第二个参数中提供的用户对象的键保存在会话中,并用于通过反序列化函数检索整个对象。

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

  1. 什么是passport.deserializeUser,它在工作流程中的什么位置?
在反序列化

函数中,您在反序列化函数的第一个参数中提供了在序列化调用中提供给 done 函数的用户对象的相同键。 因此,您的整个对象都是在该键的帮助下检索的。 这里的键是id(键可以是用户对象的任何键,即名称,电子邮件等(在反序列化函数中,该键与内存阵列/数据库或任何数据资源中的键匹配

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

id键可以是用户对象的任何键,即name,email

视觉流

passport.authenticate()-----------
                                 |  
                                 |  invokes 
                                ./
       passport.use(new LocalStrategy(
            function(username, password, done) {
           // match req.body.username and req.body.password from any 
              //data base or in memory array
               if(user_is_found_and_pass_match)
                  done(null,user);--
               else                   | *1-user passed
                                      |
                  done(null,false);---| *2-user not passed
       });                            | 
                                      |return back to
passport.authenticate() <------------ |
                      |
                      |----- if user is passed in done() (*1) ,   
                            |
    req.login()   <--------- 
              |
 //authenticate() middleware  may  invoke req.login() automatically.
              |
              | calls
             ./  
 passport.serializeUser(function(user, done) {
        done(null, user.id); 
                     |
//use 'id'to serialize, you can use other or user object itself
    });              |-->saved to session req.session.passport.user = {id:'..'}
                     |
                     |__________________
                                       |          
    passport.deserializeUser(function(id, done) {
                      ________________|
                      | 
        User.findById(id, function(err, user) {
            done(err, user);
                       |______________>user object ataches to the request as req.user
     });
      });

这里id键可以是用户对象的任何键,即name,email

给定以下express-session配置,connect-redis作为会话存储(使用 Express 4(:

redis = require('redis').createClient(6379, '127.0.0.1');
session = require('express-session');
RedisStore = require('connect-redis')(session);
app.use(session({
  store: new RedisStore({
    client: redis
  }),
  secret: 's3cret',
  resave: true,
  saveUninitialized: true
}));

您可以告诉 passport 序列化整个用户对象,而不仅仅是用户 ID。

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

整个用户对象将与会话一起保存在 Redis 中,并作为每个请求的req.user放置在请求上。

最新更新