我一直在试图理解为什么我不能让一个用户在认证后保持登录,即使认证本身是工作的。
通过尝试解决这个问题,我终于找到了问题所在。
问题如下:我有两个不同的passport策略,所以我序列化和重新序列化用户两次。如果我先用本地策略序列化用户,本地策略会起作用,但Google的不会。反之亦然。
我在app.js中添加了一条注解来强调这个问题。
这是文件
app.js
const express = require("express"),
mongoose = require("mongoose"),
bodyParser = require("body-parser"),
cookieSession = require("cookie-session"),
localStrategy = require("passport-local"),
passport = require("passport");
const LocalUser = require("./models/localuser");
const keys = require("./config/keys"); // requiring keys
const authRoutes = require("./routes/auth"); // requiring auth routes
const mainRoutes = require("./routes/main");
//Initialize express app
const app = express();
mongoose.connect("mongodb://localhost/thoughtApp"); // connectiong database
app.use(express.static(__dirname + "/public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieSession({
maxAge: 24 * 60 * 60 * 1000,
keys: [keys.session.cookieKey]
}));
//initialize passport
app.use(passport.initialize());
app.use(passport.session());
passport.use(new localStrategy(LocalUser.authenticate()));
passport.serializeUser(LocalUser.serializeUser());
passport.deserializeUser(LocalUser.deserializeUser());
app.use(function(req, res, next){
res.locals.user = req.user;
next();
});
app.use("/", mainRoutes); //main routes
app.use("/auth", authRoutes); // setup auth routes
const passportSetup = require("./config/passport-setup"); /// THIS IS THE ISSUE
// IF BeFORE LINE 33 ( passport.use(new localStrategy(LocalUser.authenticate()));, GOOGLE LOGIN WORKS BUT LOCAL DOESNT; IF AFTER, LOCAL WORKS BUT GOOGE DOESN'T; PROBABLY DUE TO SERIALIZE AND DESARIALIZE BEING USED ALREADY
app.listen(process.env.PORT || 3000, () => {
console.log("Server started.")
});
字符串
auth.js(auth routes)
const router = require("express").Router();
const passport = require("passport");
const LocalUser = require("../models/localuser");
const authCheck = function (req, res, next) {
if (!req.user) {
next();
} else {
res.redirect("/");
}
};
//login
router.get("/login", authCheck, (req, res) => {
res.render("login", {user: req.user});
});
router.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}), (req, res) => {
})
// logout
router.get("/logout", (req, res) => {
//handle with passport
req.logout();
res.redirect("/");
});
//register
router.get("/signup", authCheck, (req, res) => {
res.render("signup", {user: req.user});
});
router.post("/signup", (req, res) => {
LocalUser.register(new LocalUser({username: req.body.username}), req.body.password, (err, user) => {
if (err) {
console.log(err);
res.redirect("/auth/signup")
}
passport.authenticate("local")(req, res, () => {
console.log(user)
res.redirect("/");
})
})
})
// google auth
router.get("/google", authCheck, passport.authenticate("google", {
scope: ["profile"]
}))
//goes to google consent screen
// callback for google to redirect to
router.get("/google/redirect", passport.authenticate("google"), (req, res) => {
res.redirect("/profile");
});
module.exports = router;
型
passport-setup.js(google strategy setup)
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20");
const keys = require("./keys");
const User = require("../models/user")
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then((user) => {
done(null, user);
});
});
passport.use(new GoogleStrategy({
//options for the google strategy
callbackURL: "/auth/google/redirect",
clientID : keys.google.clientID,
clientSecret : keys.google.clientSecret
}, (accessToken, refreshToken, profile, done) => {
//passport callback function
// check if user exists already
User.findOne({googleID: profile.id}).then((currentUser) => {
if (currentUser) {
console.log("user is: " + currentUser);
done(null, currentUser);
} else {
new User({
username: profile.displayName,
googleID: profile.id
}).save().then((newUser) => {
console.log("new user created: " + newUser);
done(null, newUser);
})
}
})
})
)
型
localuser.js
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
const localUserSchema = new mongoose.Schema({
username: String,
password: String
});
localUserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("localUser", localUserSchema);
型
我该怎么解决这个问题?
2条答案
按热度按时间bxpogfeg1#
所以我一直在努力与同样的,我不知道如果你找到了解决方案,但我偶然发现了这个链接,
Linking all accounts together
因此,基本上,首先需要检查请求中是否存在req.user,如果存在,则添加要序列化的字段并调用done(null,newUser)
这个应该可以
我希望我说得够清楚了
vyu0f0g12#
这是一个非常古老的主题,但由于仍然没有答案,我希望它能帮助一些人。
我是通过使用
provider
来进行用户身份验证的(在我的例子中是GoogleStrategy
)。当使用第三方服务(如Google或Twitter)进行身份验证时,通常会提供用户个人资料信息。See reference to the official Passport.js documentation
config/passport.ts
字符串