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

wis*_*nIV 18 redis node.js express passport.js

我实现Serialize和Deserialize吗?

RedisStore设置为Express的会话存储.这是否意味着我不实现Serialize和Deserialize?它会自动发生吗?

当我没有实现这些方法时,我得到以下Express错误 - 500错误:无法将用户序列化为会话.当我实现它们时,我不确定在Deserialize中放入什么.

下面的代码似乎有效,但会话不会持续存在.我每次访问该网站时都需要登录.

在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 );
});
Run Code Online (Sandbox Code Playgroud)

Wes*_*ton 46

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

用护照实施会话

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

序列化功能的目的是返回足够的识别信息,以便在任何后续请求中恢复用户帐户.具体而言,该done()方法的第二个参数是序列化为会话数据的信息.

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

以下是" 护照指南"中讨论会话的示例:

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

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user);
  });
});
Run Code Online (Sandbox Code Playgroud)

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

passport.deserializeUser()提供了一个函数,它还接受两个参数,即识别信息(id)和再次回调函数(done).标识信息是序列化到先前请求(user.id)中的会话数据的信息.这里的回调函数需要用户配置文件作为它的第二个参数,或者在检索配置文件时引发的任何错误,因为它是第一个参数.该User.findById()函数是数据库中用户配置文件的查找函数.在此示例中,Userobject是具有该findById()函数的mongoose模型的实例.

提供给的功能passport.deserializeUser()由护照中间件调用,passport.session()在路由处理之前存储用户profile(user)req.user.

将Redis实现为会话存储

使用Redis的目的是存储会话数据服务器端,因此存储客户端的唯一数据是会话ID.同样,这与您实施护照的方式无关,只要您为应用添加了会话支持,护照就不关心会话数据的存储位置.这个关于stackoverflow的热门问题解决了如何实现Redis


A.B*_*A.B 25

有点迟,但我已经让这个视觉事物了解

  1. 何时以及如何调用策略/本地/ Facebook /等以及如何获取req.login或passport.serializeUser()以及什么是完成()?

passport.authenticate()调用您提供的相应策略作为参数,在那里匹配req.body.passwordreq.body.username与存储的数据库或内存中存储的密码和用户名.如果用户发现你把它done()作为第二个参数传递给你,否则你return false

完成的回调返回passport.authenticate().如果先前使用用户(即 done(null,user);)req,logIn()调用完成,则自动调用或由场景后面的用户调用

req.logIn() 电话 passport.serializeUser()

  1. 什么是passport.serializeUser以及在调用此函数后user.some_key在哪里?

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

Serialize函数确定应该在会话中存储来自用户对象的数据.serializeUser方法的结果附加到会话req.session.passport.user = {},例如它(因为我们提供id作为键)req.session.passport.user = {id:'xyz'}

  1. 什么是passport.deserializeUser以及它在工作流程中的位置?

在反序列化函数中,您在反序列化函数的第一个参数中提供了在序列化调用中给予完成函数的用户对象的相同键.因此,您可以借助该密钥检索整个对象.这里的密钥是id(密钥可以是用户对象的任何密钥,即名称,电子邮件等)在deSerialize函数中,密钥与内存数组/数据库或任何数据资源匹配

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

idkey可以是用户对象的任何键,即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

     });
      });
Run Code Online (Sandbox Code Playgroud)

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


And*_*yer 11

鉴于以下配置express-sessionconnect-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
}));
Run Code Online (Sandbox Code Playgroud)

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

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

passport.deserializeUser(function(user, done){
  done(null, user);
});
Run Code Online (Sandbox Code Playgroud)

整个用户对象将与Redis中的会话一起保存,并根据req.user每个请求放在请求中.