Passport.js 多登录系统无法正常工作
Passport.js Multiple login system is not working correctly
我收到一个奇怪的错误,因为我的所有登录系统都正常工作,包括系统中的本地登录以及 Google 和 Facebook 登录。当我已经注册了 Facebook 帐户并尝试注册 Google 帐户时,问题就出现了 google,Facebook 反之亦然。我正在使用 passport.js
进行身份验证和登录系统,这里是一些代码:
const express = require("express");
const app = express();
const BodyParser = require('body-parser');
const ejs = require('ejs');
const session = require("express-session");
const passport = require("passport");
const LocalStratgy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const findOrCreate = require('mongoose-findorcreate');
const mongoose = require('mongoose');
const { static } = require("express");
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.use(BodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect('mongodb://localhost/userDB', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const userSchema = new mongoose.Schema( {
email: String,
password: String,
googleId: String,
facebookId: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
/* userSchema.plugin(encrypt,{secret: process.env.SECRET, encryptedFields: ['password']}); */
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStratgy(User.authenticate()));
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 GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRETS,
callbackURL: "http://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FB_APP_SECRETS,
callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get("/" ,(req, res) => {
res.render('home');
});
app.get('/auth/google',
passport.authenticate('google', { scope: ['profile'] }));
app.get('/auth/google/secrets',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect secrets.
res.redirect('/secrets');
});
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, secrets .
res.redirect('/secrets');
});
app.get("/login" ,(req, res) => {
res.render('login');
});
app.get("/register" ,(req, res) => {
res.render('register');
});
app.get("/secrets", (req, res) => {
if(req.isAuthenticated()){
res.render("secrets");
}else{
res.redirect("/login");
}
})
app.post("/register", (req, res) => {
User.register({username: req.body.username}, req.body.password, function(err, user){
if(err){
console.log(err);
res.redirect("/register");
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
})
}
})
});
app.post("/login", (req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, err => {
if(err){
console.log(err);
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
})
});
app.get("/logout", (req, res) => {
req.logOut();
res.redirect("/");
})
注意:单独使用 Facebook 和 Google 身份验证就像一个魅力,但当两者一起使用时会引发错误。我将 Facebook 和 Google id 存储在我的数据库中,如屏幕截图所示: 本地系统在 Facebook 上工作得很好,Google 没问题。
如果您遵循护照文件,那么它可能不太正确您的用法。
以下将仅根据 facebook Id 创建一个帐户
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
以下将仅根据google Id
创建一个帐户
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
但是,我很确定你的用户是通过电子邮件识别的。
您的上述查询将创建 2 个具有相同电子邮件地址的单独 _id。
因此您的查询应该更正为类似如下
User.updateOne({ email: profile.email }, { googleId: profile.id }, { upsert: true })
和
User.updateOne({ email: profile.email }, { facebookId: profile.id }, { upsert: true })
以上将检查电子邮件是否存在,如果存在,更新googleId。如果不存在,请创建一个新用户。
此外,您的架构缺少 username
字段
我收到一个奇怪的错误,因为我的所有登录系统都正常工作,包括系统中的本地登录以及 Google 和 Facebook 登录。当我已经注册了 Facebook 帐户并尝试注册 Google 帐户时,问题就出现了 google,Facebook 反之亦然。我正在使用 passport.js
进行身份验证和登录系统,这里是一些代码:
const express = require("express");
const app = express();
const BodyParser = require('body-parser');
const ejs = require('ejs');
const session = require("express-session");
const passport = require("passport");
const LocalStratgy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const findOrCreate = require('mongoose-findorcreate');
const mongoose = require('mongoose');
const { static } = require("express");
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.use(BodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect('mongodb://localhost/userDB', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const userSchema = new mongoose.Schema( {
email: String,
password: String,
googleId: String,
facebookId: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
/* userSchema.plugin(encrypt,{secret: process.env.SECRET, encryptedFields: ['password']}); */
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStratgy(User.authenticate()));
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 GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRETS,
callbackURL: "http://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FB_APP_SECRETS,
callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get("/" ,(req, res) => {
res.render('home');
});
app.get('/auth/google',
passport.authenticate('google', { scope: ['profile'] }));
app.get('/auth/google/secrets',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect secrets.
res.redirect('/secrets');
});
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, secrets .
res.redirect('/secrets');
});
app.get("/login" ,(req, res) => {
res.render('login');
});
app.get("/register" ,(req, res) => {
res.render('register');
});
app.get("/secrets", (req, res) => {
if(req.isAuthenticated()){
res.render("secrets");
}else{
res.redirect("/login");
}
})
app.post("/register", (req, res) => {
User.register({username: req.body.username}, req.body.password, function(err, user){
if(err){
console.log(err);
res.redirect("/register");
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
})
}
})
});
app.post("/login", (req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, err => {
if(err){
console.log(err);
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
})
});
app.get("/logout", (req, res) => {
req.logOut();
res.redirect("/");
})
注意:单独使用 Facebook 和 Google 身份验证就像一个魅力,但当两者一起使用时会引发错误。我将 Facebook 和 Google id 存储在我的数据库中,如屏幕截图所示:
如果您遵循护照文件,那么它可能不太正确您的用法。
以下将仅根据 facebook Id 创建一个帐户
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
以下将仅根据google Id
创建一个帐户User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
但是,我很确定你的用户是通过电子邮件识别的。
您的上述查询将创建 2 个具有相同电子邮件地址的单独 _id。
因此您的查询应该更正为类似如下
User.updateOne({ email: profile.email }, { googleId: profile.id }, { upsert: true })
和
User.updateOne({ email: profile.email }, { facebookId: profile.id }, { upsert: true })
以上将检查电子邮件是否存在,如果存在,更新googleId。如果不存在,请创建一个新用户。
此外,您的架构缺少 username
字段