您如何解释Passport对外行人序列化和反序列化方法的工作流程。
调用user.id
之后passport.serializeUser
去哪儿了?
我们正在调用passport.deserializeUser
之后它在哪里适合工作流程?
// 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);
});
});
我仍然试图绕过它。我有一个完整的工作应用程序,并没有遇到任何类型的错误。
我只想了解这里究竟发生了什么?
感谢任何帮助。
答案 0 :(得分:357)
- 醇>
user.id
在调用passport.serializeUser
之后去了哪里?
用户ID(作为done
函数的第二个参数提供)保存在会话中,稍后用于通过deserializeUser
函数检索整个对象。
serializeUser
确定用户对象的哪些数据应存储在会话中。 serializeUser方法的结果作为req.session.passport.user = {}
附加到会话。例如,它将(因为我们提供用户ID作为密钥)req.session.passport.user = {id: 'xyz'}
- 我们正在调用
醇>passport.deserializeUser
之后它在哪里适合工作流程?
deserializeUser
的第一个参数对应于赋予done
函数的用户对象的键(参见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
});
答案 1 :(得分:18)
对于使用Koa和koa-passport的任何人:
知道在serializeUser方法中设置的用户密钥(通常是该用户的唯一ID)将存储在:
this.session.passport.user
在deserializeUser中设置done(null, user)
时,'user'是数据库中的某个用户对象:
this.req.user
要么
this.passport.user
由于某种原因{delerializeUser方法中调用done(null,user)时,{a 1}} Koa上下文永远不会被设置。
因此,您可以在调用app.use(passport.session())之后编写自己的中间件,将其放入this.user中,如下所示:
this.user
如果你不清楚serializeUser和deserializeUser是如何工作的,那就试着在twitter上点击我。 @yvanscher
答案 2 :(得分:3)
Passport 使用 serializeUser
函数将用户数据(成功验证后)保存到会话中。函数 deserializeUser
用于从会话中检索用户数据。
serializeUser
和 deserializeUser
函数都检查传递给它们的第一个参数,如果它是函数类型,则 serializeUser
和 deserializeUser
什么都不做,但将这些函数放在之后将调用的函数堆栈(当传递的第一个参数不是函数类型时)。
Passport 需要进行以下设置才能在会话中进行身份验证后保存用户数据:
app.use(session({ secret: "cats" }));
app.use(passport.initialize());
app.use(passport.session());
使用的中间件的顺序很重要。重要的是要了解当新的授权请求开始时会发生什么:
会话中间件创建会话(使用来自 sessionStore
的数据)。
passport.initialize
将 _passport
对象分配给请求对象,检查是否存在会话对象,是否存在,并且其中存在字段 passport
(如果不存在 - 创建一个),将该对象分配给 session
中的 _passport
字段。最后,它看起来像这样:
req._passport.session = req.session['passport']
因此,分配给 session
的 req.session.passport
字段 references 对象。
passport.session
在 user
中查找 req._passport.session
字段,如果找到,则将其传递给 deserializeUser
函数并调用它。 deserializeUser
函数将 req._passport.session.user
分配给请求对象的 user
字段(如果在 req._passport.session.user
中找到)。这就是为什么,如果我们像这样在 serializeUser
函数中设置用户对象:
passport.serializeUser(function(user, done) {
done(null, JSON.strignify(user));
});
然后我们需要解析它,因为它在 JSON
字段中保存为 user
:
passport.deserializeUser(function(id, done) {
// parsed user object will be set to request object field `user`
done(err, JSON.parse(user));
});
因此,当您设置 Passport 时,首先调用 deserializeUser
函数,将您的回调放入 _deserializers
函数堆栈中。第二次,它将在 passport.session
中间件中调用以将 user
字段分配给请求对象。这也会在分配 passport.deserializeUser()
字段之前触发我们的回调(我们放入 user
)。
serializeUser
函数在您设置 Passport 时首先调用(类似于 deserializeUser
函数),但它将用于序列化用户对象以保存在会话中。第二次,它会在 login/logIn (alias)
方法中调用,由 Passport 附加,用于保存会话中的用户对象。 serializeUser
函数还会检查 _serializers
堆栈是否已推送给它的函数(其中一个添加,在我们设置 Passport 时):
passport.serializeUser(function(user, done) ...
并调用它们,然后将用户对象(strignified)或用户 ID 分配给 req._passport.session.user
。请务必记住,session
字段直接引用 passport
对象中的 req.session
字段。这样用户在会话中保存(因为 req._passport.session
引用对象 req.session.passport
,并且 req._passport.session
在每个传入请求中被 passport.initialize
中间件修改)。
当请求结束时,req.session
数据将存储在 sessionStore
中。
授权成功后,当第二个请求开始时会发生什么:
session
中间件从 sessionStore
获取会话,我们的用户数据已保存在其中passport.initialize
检查是否有会话并将 req.session.passport
分配给 req._passport.session
passport.session
检查 req._passport.session.user
并将其反序列化。在此阶段(如果 req._passport.session.user
为真),我们将让 req.user
和 req.isAuthenticated()
返回 true
。