所以我已经考虑了一段时间了。
对于那些不想使用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);
模式具有密码字段。现在,社交登录将不会发送用户密码,但是对于本地登录,我们将需要使用密码。
我能想到的唯一选择是创建两个具有密码的模式,一个没有密码的模式。
问题:人们通常会这样做吗?比如说最好的方法还是有人可以建议我一个更好的替代方法
答案 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
,如果令牌正确,则显示错误。
希望我的答案可以帮助您:)