使用带有护照和续集的谷歌社交登录时多次执行查询

Posted

技术标签:

【中文标题】使用带有护照和续集的谷歌社交登录时多次执行查询【英文标题】:Query executing multiple times when using google social login with passport and sequelize 【发布时间】:2015-10-29 18:10:43 【问题描述】:

嗨,伙计们,这是我的第一个问题,所以请耐心等待,我在使用带有 sequelize 的护照时遇到问题,问题发生在我在数据库中搜索记录以检查用户是否已经存在但当护照反序列化时, Sequelize 执行五个“选择查询”,代码类似于我在 scotch.io 中找到的一个,我只是将 sequelize api 附加到它:

module.exports = function (passport) 

    // used to serialize the user for the session
    passport.serializeUser(function (user, done) 
        done(null, user.iduser);
    );

    // used to deserialize the user
    passport.deserializeUser(function (id, done) 
        userModel.findById(id)
        .then(function (userVo) 
            done(null, userVo);
        ).catch(function(err) 
            if(err)
                throw err;
        )
    );

    passport.use(new GoogleStrategy(
            clientID: 'XXXXX',
            clientSecret: 'XXXXXX',
            callbackURL: 'XXXXX'
        ,
        function (token, refreshToken, profile, done) 
            // make the code asynchronous
            // User.findOne won't fire until we have all our data back from Google
            process.nextTick(function () 
                // try to find the user based on their google id
                sequelize.transaction(function (t) 
                        return sociaLoginModel.findOne(
                                where: 
                                    idprovided: profile.id,
                                    logintype: constants.GOOGLE_LOGIN_TYPE
                                
                            , 
                                transaction: t
                            )
                            .then(function (socialLoginResult) 
                                //if user was found, then retrieve and create a session for him returning the value to done
                                var socialLoginVo;
                                if (socialLoginResult) 
                                    socialLoginVo = socialLoginResult.dataValues
                                    return userModel.findById(socialLoginVo.tb11_fkuser, 
                                            transaction: t
                                        )
                                        .then(function (userResult) 
                                            return userResult.dataValues;
                                        );
                                 else 
                                    return individualsModel.create(
                                            name: profile.displayName
                                        , 
                                            transaction: t
                                        )
                                        .then(function (individualsResult) 
                                            var individualsVo = individualsResult.dataValues
                                            return userModel.create(
                                                    email: profile.emails[0].value,
                                                    user_type: constants.USER_INDIVIDUALS,
                                                    tb12_fkindividuals: individualsVo.idindividuals
                                                , 
                                                    transaction: t
                                                )
                                                .catch(function (err) 
                                                    if (err)
                                                        throw err;
                                                )
                                                .then(function (userResult) 
                                                    var userVo = userResult.dataValues
                                                    console.log(typeof profile.id)
                                                    return sociaLoginModel.create(
                                                            idprovided: profile.id,
                                                            token: token,
                                                            logintype: constants.GOOGLE_LOGIN_TYPE,
                                                            tb11_fkuser: userVo.iduser
                                                        , 
                                                            transaction: t
                                                        )
                                                        .then(function (sociaLoginResult) 
                                                            return userVo
                                                        )
                                                        .catch(function(err) 
                                                            if(err)
                                                                throw err;
                                                        )
                                                )
                                        ).catch(function(err) 
                                            if(err)
                                                throw err
                                        )
                                
                            ).catch(function(err) 
                                if(err)
                                    throw err
                            )
                    ).then(function (result) 
                        return done(null, result);
                    ).catch(function (err) 
                        if (err) 
                            return done(err)
                    );
            )
        ))
;

此代码在一个文件中,我将其用作 app.js 调用中的中间件:

require('./logins/google')(passport);

我也使用本地登录和 facebook 执行此操作,代码几乎与 google 登录中的代码相同,为什么 Sequelize 会执行这么多查询?难道我做错了什么??我怎样才能最小化这个数字?谢谢。

【问题讨论】:

我的猜测是您的 所有 前端请求(CSS、JS、favicon.ico)导致 passport.deserializeUser() 被调用。 我做这个请求的路由是'/',我唯一要做的就是验证req.isAutenticated()如果是,然后用用户电子邮件渲染索引,如果不是,只渲染而不设置页面的属性。但这算作反序列化用户的一个查询不是吗? 这取决于您的页面。例如,您使用的是express.static() 吗? 是的,它是这样声明的:app.use(express.static(__dirname + '/public')); 我是 nodejs 和 javascript 的新手,我不知道它到底是做什么的,因为我是从 express-generator 生成的/跨度> 移动express.static()中间件之前 app.use(passport.initialize())时请求数可能会下降。 【参考方案1】:

根据您的 cmets,我推断您的 Express/Passport 设置与此有些相似:

app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(...));

因为 Express 是按顺序调用中间件的,这意味着每个请求在到达静态中间件之前都会先经过 Passport 中间件。

Passport 中间件调用passport.deserializeUser(...),因此对于最终将由静态中间件处理的请求(例如,CSS/JS/html 文件)也会调用它。

如果您重新排列中间件顺序,静态中间件将首先为那些特定请求调用,并且只有当它无法处理请求时(例如,对于应该由您的一个路由处理的请求)才会通过对 Passport 中间件的请求:

app.use(express.static(...));
app.use(passport.initialize());
app.use(passport.session());

【讨论】:

它对我来说非常有效,我不知道这个问题,谢谢@robertklep 它处理了额外的调用,但我收到了这个错误:未处理的拒绝错误:passport.initialize() 中间件未使用 @iMad 可能会为此提出一个新问题,包括您的 Express 设置。

以上是关于使用带有护照和续集的谷歌社交登录时多次执行查询的主要内容,如果未能解决你的问题,请参考以下文章

使用带有反应 2 的谷歌登录按钮

如何处理小部件的谷歌登录

我应该如何在登录时使用续集和护照获得验证错误

如何在 laravel 中使用社交名流和护照创建 REST API

Ionic 4/5 - 带有服务的模态窗口中的谷歌地图

如何获取特定登录用户的谷歌日历 URL