正确的方法来使用本地护照和Facebook / Google护照

时间:2018-12-23 23:50:33

标签: node.js express mongoose passport.js

所以我已经考虑了一段时间了。

对于那些不想使用facebook / google进行注册的人,我正在使用本地护照;对于那些希望使用社交登录快速进行注册的人,我正在使用本地护照。

因为这是我的第一个应用程序,所以我无法理解如何将它们一起使用。

例如,我正在创建一个用于存储用户数据的架构

const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
    fullName: String,
    email: String,
    passowrd: String, 
    image: String
}) 


module.exports = mongoose.model('User', userSchema);

模式具有密码字段。现在,社交登录将不会发送用户密码,但是对于本地登录,我们将需要使用密码。

我能想到的唯一选择是创建两个具有密码的模式,一个没有密码的模式。

问题:人们通常会这样做吗?比如说最好的方法还是有人可以建议我一个更好的替代方法

1 个答案:

答案 0 :(得分:1)

您的User schema应该是:

const mongoose = require('mongoose')
var Schema=mongoose.Schema;
var bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({
    fullName: {type:String,required:true,default:''},
    email: {type:String,required:true,unique:true},
    email_verified:{type:Boolean,default:false},
    verify_token:{type:String,default:null},
    provider:{type:String,default:'email'},
    provider_id:{type:String,default:null},
    password: {type:String}, 
    password_reset_token:{type:String,default:null},
    image: {type:String,default:null},
    created_at:{type:Date,default:Date.now},
    updated_at:{type:Date,default:Date.now},
},{
    collection:'User'
 }); 

module.exports = mongoose.model('User', userSchema);

 module.exports.encryptPassword=function(password)
{
 var salt= bcrypt.genSaltSync(10);
 var hash=  bcrypt.hashSync(password,salt,null);    
 return hash;
}


module.exports.validPassword=function(password,hash){
 return bcrypt.compareSync(password,hash);  
}

这里添加了一些额外的有用字段:

  • 电子邮件已验证:用于检查用户是否已验证电子邮件

  • 提供者:注册提供者,例如facebook,google..etc ...默认 如果用户使用电子邮件进行注册,则为电子邮件。

  • provider_id :提供商ID是社交网络提供的用户的唯一ID 媒体(Facebook,google)

  • password_reset_token :是随机令牌字符串,当用户忘记密码并通过电子邮件发送此令牌以重设密码时

  
      
  • 现在,当用户使用电子邮件注册时,保存用户输入的密码。

  •   
  • 使用社交媒体提供商(facebook,google)进行用户注册时..然后生成随机字符串,使用bcrypt创建密码   并保存到密码字段,请记住:对于使用社交媒体注册的用户,密码字段不能为空。

  •   

现在创建文件passport.js

var FacebookStrategy = require('passport-facebook').Strategy;
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;

var User       = require('../models/user');


module.exports = function(passport) {

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
        done(err, user);
    });
});


  passport.use(new FacebookStrategy({

    clientID        : 'clientID',
    clientSecret    : 'clientSecret',
    callbackURL     : 'callbackURL'

},
// facebook will send back the token and profile
function(token, refreshToken, profile, done) {
    console.log("TOKEN = "+token);
    console.log("REFRESH TOKEN = "+refreshToken);
    console.log("PROFILE = "+JSON.stringify(profile));

        // find the user in the database based on their facebook id
        User.findOne({ 'provider_id' : profile.id }, function(err, user) {

            if (err)
                return done(err);

            if (user) {
                return done(null, user); // user found, return that user
            } else {
                console.log(profile);
                let randomString= Math.random().toString(36).substring(2);
                var newUser = new User({
                  fullName  : profile.displayName,
                  email :profile.emails[0].value, 
                  email_verified : true,
                  password : User.encryptPassword(randomString),
                  image : 'get user image from response',
                  provider : 'facebook',
                  provider_id : profile.id,    
                });

               newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
           }

        });

}));



  passport.use(new GoogleStrategy({
    clientID        : 'clientID',
    clientSecret    : 'clientSecret',
    callbackURL     : 'callbackURL',
  },
function(token, refreshToken, profile, done) {

         User.findOne({ 'provider_id' : profile.id }, function(err, user) {
            if (err)
                return done(err);
            if (user) {
          return done(null, user);
            } else {
                let randomString= Math.random().toString(36).substring(2);
                var newUser = new User({
                  fullName  : profile.displayName,
                  email :profile.emails[0].value, 
                  email_verified : true,
                  password : User.encryptPassword(randomString),
                  image : 'get user image from response',
                  provider : 'google',
                  provider_id : profile.id,    
                });
                newUser.save(function(err) {
                    if (err)
                        throw err;
                    return done(null, newUser);
                });
            }
        });
}));


}

特别有用的注意:当用户使用facebook / google注册时,请设置email_verified:true,因为用户已经通过提供商验证了他的电子邮件

当用户使用其电子邮件集email_verified:false注册并生成randon令牌并在创建用户时设置verify_token:'random token'时,然后使用NodeMailer发送带有此随机令牌,验证链接的帐户验证电子邮件

生成用于处理电子邮件验证的新路由,例如/verify,当用户点击电子邮件中的链接时,此路由将处理请求,通过verify_token查找用户并设置email_verified : true,如果令牌正确,则显示错误。

希望我的答案可以帮助您:)