【问题标题】:Mongoose User model for handling local and social auth providers用于处理本地和社交身份验证提供者的 Mongoose 用户模型
【发布时间】:2017-07-25 08:04:55
【问题描述】:

所以我正在开发一个 Express(带有 Mongoose 和 Passport)应用程序,我想将 facebook 作为一种身份验证方法。我已经完成了它并且它有效,但我认为我没有合适的用户模型来处理多个社交提供者的身份验证过程。我想合并不同的社交账户。这是我当前适用于 facebook auth 的用户模型:

let userSchema = mongoose.Schema({
    email: { type: String, unique: true },
    name: { type: String },
    password: { type: String },
    facebookId: String,
    facebookToken: String
}, { timestamps: true });

我想到了以下两种方法,但我不确定它们是否可行以及哪种方法最灵活且独立于社交提供者。 我正在考虑拥有这样的本地和社交数组:

let userSchema = mongoose.Schema({
    local: {
        email: { type: String, unique: true },
        name: { type: String },
        password: { type: String },
    },
    facebook: {
        id: String,
        token: String,
        email: String,
        name: String
    },
    google: {
        id: String,
        token: String,
        email: String,
    }
}, { timestamps: true });

第三种方法只是覆盖社交提供者 ID(我不确定这是否可以)。

let userSchema = mongoose.Schema({
        email: { type: String, unique: true },
        name: { type: String },
        id: String,
        token: String,
    }, { timestamps: true });

【问题讨论】:

  • 我正在使用第二种方法来处理本地和社交登录。但是,当我尝试使用社交资料登录时,我收到来自 mongo 的错误,即必须填写本地的必填字段。我标记了一些需要的本地配置文件数据。有没有更好的办法?

标签: facebook express mongoose oauth passport.js


【解决方案1】:

所以我为自己找到了一个可行的解决方案,它可能会帮助其他有同样问题的人。在我的用户模型中,我有我常用的字段,对于每个社交提供者,我都有一个单独的数组,如下所示(users/User.js):

let userSchema = mongoose.Schema({
    email: { type: String, unique: true },
    name: { type: String },
    password: { type: String },
    roles: [String],
    confirmation_code: String,
    confirmed: { type: Boolean, default: false },
    facebook: {
        id: String,
        token: String,
        email: String,
        name: String
    },
    google: {
        id: String,
        token: String,
        email: String,
        name: String
    }
}, { timestamps: true });

在通过社交提供商进行身份验证时,我会额外检查是否已经存在使用相同电子邮件的用户。如果没有,我创建一个新用户。如果是这样,我只需将社交提供者数据(id、令牌等)添加到已经存在的用户数组中,就像这样(config/passport.js):

passport.use(new FacebookStrategy({
    clientID: oauth.facebook.clientID,
    clientSecret: oauth.facebook.clientSecret,
    callbackURL: oauth.facebook.callbackURL,
    profileFields: ['id', 'emails', 'name']
},
    function (accessToken, refreshToken, profile, done) {
        process.nextTick(function () {
            User.findOne({
                $or: [
                    { 'facebook.id': profile.id },
                    { 'email': profile.emails[0].value }
                ]
            }, function (err, user) {
                if (err) {
                    return done(err);
                }

                if (user) {
                    if (user.facebook.id == undefined) {
                        user.facebook.id = profile.id;
                        user.facebook.token = accessToken;
                        user.facebook.email = profile.emails[0].value;
                        user.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
                        user.save();
                    }

                    return done(null, user);

                } else {
                    let newUser = new User();
                    newUser.facebook.id = profile.id;
                    newUser.facebook.token = accessToken;
                    newUser.facebook.email = profile.emails[0].value;
                    newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
                    newUser.name = profile.name.givenName + ' ' + profile.name.familyName;
                    newUser.email = profile.emails[0].value;

                    newUser.save(err => {
                        if (err) {
                            console.log(err);
                            throw err;
                        }

                        return done(null, newUser);
                    });
                }
            });
        });
    }
));

通过这种方法,您可以将一个个人资料与多个社交服务提供商联系起来。然而,有一个缺点。如果用户第一次通过社交提供者注册新的个人资料,他将没有密码,因为社交提供者不会返回密码数据(duh)。之后他只需要通过他的个人资料更改(设置)他的密码。

【讨论】:

    猜你喜欢
    • 2021-11-24
    • 2021-05-17
    • 2022-01-01
    • 2014-10-14
    • 1970-01-01
    • 2015-08-05
    • 2021-03-22
    • 1970-01-01
    • 2017-02-06
    相关资源
    最近更新 更多