facebook - 用于处理本地和社交身份验证提供程序的Mongoose用户模型

标签 facebook express mongoose oauth passport.js

因此,我正在开发一个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 });

最佳答案

因此,我为自己找到了一个可行的解决方案,该解决方案可能会帮助遇到相同问题的其他人。在我的用户模型中,我有我通常的字段,对于每个社交提供者,我都有一个单独的数组,如下所示(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, token 等)添加到已经存在的用户数组中,例如(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)。之后,他只需要通过个人资料更改(设置)密码即可。

关于facebook - 用于处理本地和社交身份验证提供程序的Mongoose用户模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42608919/

相关文章:

JavaScript - Express - MongoDb - Mongoose findOneAndUpdate 返回未定义

php - 提高 Facebook FQL 的性能和可用性

ios - iOS 上的 PhoneGap Facebook Connect 插件

ruby-on-rails - Ruby on Rails Omniauth facebook 不返回电子邮件

angularjs - 从 Azure Blob for Express.js 服务器提供 HTML 文件

javascript - express 中可变数量的路线参数?

css - 如何从 HTML 播放 Facebook 视频?

javascript - 如何使用node js mongoose保存后返回json数据

node.js - MongoDB-查询优化

Mongoose:如何定义字段的组合是唯一的?