当前位置: 首页 > 知识库问答 >
问题:

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

牟飞沉
2023-03-14

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

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

共有3个答案

蒯华彩
2023-03-14

给定以下使用 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 放置在请求中。

杜哲彦
2023-03-14

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

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

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

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

req.logIn() 调用 passport.serializeUser()

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

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

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

获取的对象以 req.user 身份附加到请求对象

ID键可以是用户对象的任何键,即名称,电子邮件

视觉流

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键可以是用户对象的任何键,即名称,电子邮件

袁秦迟
2023-03-14

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

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

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

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

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

js prettyprint-override">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() 函数是数据库中用户配置文件的查找函数。在此示例中,用户 object 是具有 findById() 函数的猫鼬模型的实例。

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

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

 类似资料:
  • 问题内容: 我注意到存储在Redis中的某些序列化对象在反序列化方面遇到问题。 当我对Redis中存储的对象类进行更改时,通常会发生这种情况。 我想了解问题,以便为解决方案设计一个清晰的方案。 我的问题是,什么导致反序列化问题?移除公共/私人财产会引起问题吗?也许添加新属性?向类添加新功能会产生问题吗?那么更多的构造函数呢? 在我的序列化对象中,我有一个属性Map,如果我更改(更新了一些属性,添加

  • 问题内容: Golang中将结构序列化和反序列化为字符串的最佳方法(完整性和性能)是什么,反之亦然? 例如,如果我有这个结构: 我想将其存储在Redis上并取回。我试过保存,整型和字符串,这很好,但是如何存储结构对象? 问题答案: 使用gob和base64可以解决问题,例如: 当您需要序列化自定义结构或类型(例如struct)时,只需添加以下行:

  • 主要内容:1 Java序列化和反序列化,2 Java序列化的优点,3 java.io.Serializable接口,4 Java ObjectOutputStream,5 Java ObjectInputStream,6 Java序列化的例子,7 Java反序列化的例子1 Java序列化和反序列化 Java中的序列化是一种将对象状态写入字节流的机制。它主要用于Hibernate,RMI,JPA,EJB和JMS技术。 序列化的反向操作称为反序列化,其中字节流被转换为对象。序列化和反序列化过程与平台

  • 问题内容: 您如何向外行解释Passport的序列化和反序列化方法的工作流程。 叫到哪里去了? 我们紧接着在工作流程中调用它吗? 我仍在努力寻找解决方案。我有一个完整的工作应用程序,没有遇到任何类型的错误。 我只是想了解这里到底发生了什么? 任何帮助表示赞赏。 问题答案: 叫到哪里去了? 用户ID(您作为函数的第二个参数提供)被保存在会话中,以后用于通过函数检索整个对象。 确定应将用户对象的哪些数

  • 本文向大家介绍C#实现的json序列化和反序列化代码实例,包括了C#实现的json序列化和反序列化代码实例的使用技巧和注意事项,需要的朋友参考一下

  • 本文向大家介绍Java 序列化和反序列化实例详解,包括了Java 序列化和反序列化实例详解的使用技巧和注意事项,需要的朋友参考一下 Java 序列化和反序列化实例详解 在分布式应用中,对象只有经过序列化才能在各个分布式组件之间传输,这就涉及到两个方面的技术-发送者将对象序列化,接受者将对象反序列化,下面就是一个很好的例子! 1.实体-Employee 2.SerializeHelper 3.测试类

  • 我正在尝试使用kryo序列化和反序列化到二进制。我想我已经完成了序列化,但似乎无法反序列化。下面是我正在处理的代码,但最终我想存储一个字节[],然后再次读取它。文档只显示了如何使用文件。

  • 本文向大家介绍什么是序列化与反序列化?相关面试题,主要包含被问及什么是序列化与反序列化?时的应答技巧和注意事项,需要的朋友参考一下 序列化:将对象状态转换为可保持或传输的格式的过程。将对象实例的字段及类的名称转换成字节流,然后把字节流写入数据流 反序列化:将流转换为对象。 这两个过程结合起来,可以轻松地存储和传输数据。