首页 > 解决方案 > 使用 Passport,如果我使用令牌进行身份验证,序列化用户的目的是什么?

问题描述

我将passport-google-oauth20其用作我的应用程序的唯一身份验证形式。一切似乎都很好,我可以使用verify回调护照提供的身份验证用户并将他存储在数据库中。

在这个应用程序中,我只会使用 google 对用户进行身份验证并检查他是否存在于数据库中。我不会向谷歌提出更多请求,也不会从谷歌获取更多信息。

我注意到护照的回调函数背后发生了很多神奇的事情。我对如何serializeUserdeserializeUser工作有一个模糊的理解,但我不确定什么时候有必要。

护照提供的回调函数在localStorage上设置了一个JWT,所以即使我设置{ session: false }了重定向选项,我还需要序列化用户吗?

这是一些清除问题的代码

passport.use(
    new GoogleStrategy({
        clientID: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        callbackURL: 'http://localhost:3000/auth/google/redirect'
    },
    (accessToken, refreshToken, profile, done) => {
        // console.log('TCL: profile', profile); -> Gives profile info
        // console.log('TCL: refreshToken', refreshToken); -> Null
        // console.log('TCL: accessToken', accessToken); 
        // This attaches the user profile to the req object
        done(null, profile);
    })
);

以下是路线:

app.use(passport.initialize());

app.get(
    '/auth/google',
    passport.authenticate('google', { scope: ['profile', 'email'] })
);

app.get(
    '/auth/google/redirect',
    passport.authenticate('google', { session: false }),
    (req, res) => {
        console.log(req.user);
        res.redirect('/');
    }
);

我能够获得个人资料和我需要的所有信息。我还需要序列化用户吗?

标签: node.jsexpressauthenticationoauth-2.0passport-google-oauth2

解决方案


serializeUser 和 deserializerUser 函数用于设置 cookie 和读取该 cookie。

在 google oauth 中,当用户首次使用 google 帐户登录时,您会访问其个人资料并找到要保存在数据库中的唯一标识属性。该标识属性应该是 profile.id。因此,您将用户的 profile.id 存储在数据库中。

下次,当用户登录时,您需要识别用户,否则您将一遍又一遍地保存相同的 profile.id。为了记住用户,您创建 cookie。当用户登录时,您获取该 profile.id 并查询该 profile.id 是否保存在数据库中。此操作在护照回调函数中完成,如果用户存在,则护照将有权访问该用户。

passport.use(new GoogleStrategy({
clientID:keys.googleClientID,
clientSecret:keys.googleClientSecret,
callbackURL:"/auth/google/callback"}, (accessToken,refreshToken, profile,done)=>{
     User.findOne({googleId:profile.Id}).then((user)=>{
        if(user){ //it checks if the user is saved in the database
            done(null,user)
        }else {
            new User({googleId:profile.id}).save().then((user)=>done(null,user))
        }
     })   
}))

当passport.js 访问到用户后,它会自动调用serializeUser 函数,获取用户唯一标识的属性user.id,并将其注入到cookie 中,该cookie 发送到客户端响应头。

passport.serializeUser((user,done)=>{
//user.id is not profile id. it is id that created by the database
    done(null,user.id)
})

一旦浏览器收到响应,它将cookie保存在一个文件中,当它向同一服务器发出后续请求时,它会自动将该cookie附加到请求中。Passport.js 将提取唯一标识信息 user.id 并将其传递给数据库,数据库将识别客户端。

passport.deserializeUser((id,done)=>{
    User.findById(id).then((user)=>{
        done(null,user)
    })
})

推荐阅读