简体   繁体   English

password.js中的本地和Google策略:序列化用户时出现问题

[英]Local and Google strategy in passport.js: issue when serializing user

I've been trying to understand why I couldn't keep an user logged in once authenticated even though authentication itself was working. 我一直在试图理解为什么即使身份验证本身可以正常工作,但是一旦身份验证我就无法保持用户登录。 I even posted a question here: Passport.js - Local strategy doesn't authenticate 我什至在这里发布了一个问题: Passport.js-本地策略无法验证

By trying to fix the issue, I finally worked out what's wrong. 通过尝试解决此问题,我终于弄清楚了问题所在。

The issue is the following: I have two different passport strategy, so I am serializing and deserializing the user twice. 问题如下:我有两种不同的通行证策略,因此我要对用户进行两次序列化和反序列化。 If I serialize the user with the local strategy first, local strategy will work, but Google's won't. 如果我首先使用本地策略对用户进行序列化,则本地策略会起作用,但Google不会。 And vice versa. 反之亦然。

I put a comment to highlight the problem in app.js. 我发表评论以突出app.js中的问题。

Here's the files: 这是文件:

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) auth.js(身份验证路由)

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) Passport-setup.js(谷歌策略设置)

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 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);

How can I solve this? 我该如何解决?

So I have been struggling with the same and I don't know if you found a solution but I stumbled upon this link, 所以我一直在努力解决这个问题,我不知道您是否找到了解决方案,但我偶然发现了这个链接,

Linking all accounts together 将所有帐户关联在一起

So basically, you first need to check is in the request is req.user exists, if so add the fields you want to serialize and call done(null,newUser) 所以基本上,您首先需要检查请求是否存在req.user,如果存在,则添加要序列化的字段并调用done(null,newUser)

This should do the trick, 这应该可以解决问题,

I hope i was clear enough 我希望我足够清楚

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM