Passport使用serializeUser函数将用户数据(身份验证成功后)持久化到会话中。函数deserializeUser用于从会话中检索用户数据。
serializeUser和deserializeUser函数都检查传递给它们的第一个参数,如果它是函数类型,serializeUser和deserializeUser函数什么都不做,而是将这些函数放在一个函数堆栈中,之后将被调用(当传递的第一个参数不是函数类型时)。
在会话中进行身份验证后,Passport需要以下设置来保存用户数据:
app.use(session({ secret: "cats" }));
app.use(passport.initialize());
app.use(passport.session());
使用中间件的顺序很重要。重要的是,当一个新的授权请求开始时,会发生什么:
session middleware creates session (using data from the sessionStore).
passport.initialize assigns _passport object to request object, checks if there's a session object, and if it exists, and field passport exists in it (if not - creates one), assigns that object to session field in _passport. At the end, it looks, like this:
req._passport.session = req.session['passport']
So, session field references object, that assigned to req.session.passport.
passport.session looks for user field in req._passport.session, and if finds one, passes it to deserializeUser function and calls it. deserializeUser function assigns req._passport.session.user to user field of request object (if find one in req._passport.session.user). This is why, if we set user object in serializeUser function like so:
passport.serializeUser(function(user, done) {
done(null, JSON.strignify(user));
});
We then need to parse it, because it was saved as JSON in user field:
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中被调用。会话中间件将用户字段分配给请求对象。这也会在分配user字段之前触发回调(我们放在passport.deserializeUser()中)。
serializeUser函数在设置Passport时首先调用(类似于deserializeUser函数),但它将用于序列化用户对象以保存在会话中。第二次,它将在login/ login(别名)方法中被调用,由Passport附加,并用于在会话中保存用户对象。serializeUser函数还检查_serializers堆栈中已经推入它的函数(其中一个是在我们设置Passport时添加的):
passport.serializeUser(function(user, done) ...
并调用它们,然后将用户对象(经过标记)或用户id分配给req._passport.session.user。重要的是要记住session字段在req中直接引用passport字段。会话对象。这样用户就保存在会话中了(因为req._passport. conf。会话引用对象req.session。Passport和req._passport。会话在每个传入请求中通过护照进行修改。初始化中间件)。
当请求结束时,请求。会话数据将存储在sessionStore中。
成功授权后,当第二个请求开始时,会发生什么:
会话中间件从sessionStore获取会话,我们的用户数据已经保存在sessionStore中
护照。初始化检查是否有会话,并将req.session.passport分配给req._passport.session
护照。会话检查req._passport.session。用户并反序列化它。在此阶段(如果req._passport.session. conf。用户是真实的),我们将有需求。req.isAuthenticated()返回true。