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

Posted

技术标签:

【中文标题】passport.js 中的本地和 Google 策略:序列化用户时的问题【英文标题】:Local and Google strategy in passport.js: issue when serializing user 【发布时间】:2019-01-06 22:11:48 【问题描述】:

我一直在试图理解为什么我无法让用户在通过身份验证后保持登录状态,即使身份验证本身正在工作。我什至在这里发布了一个问题:Passport.js - Local strategy doesn't authenticate

通过尝试解决问题,我终于找出了问题所在。

问题如下:我有两种不同的护照策略,所以我对用户进行了两次序列化和反序列化。如果我先用本地策略序列化用户,本地策略会起作用,但谷歌不会。反之亦然。

我发表评论以突出 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(认证路由)

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

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

我该如何解决这个问题?

【问题讨论】:

您找到解决方案了吗? 【参考方案1】:

所以我一直在苦苦挣扎,我不知道您是否找到了解决方案,但我偶然发现了这个链接,

Linking all accounts together

所以基本上,您首先需要检查请求中是否存在 req.user,如果存在,请添加要序列化的字段并调用 done(null,newUser)

这应该可以解决问题,

我希望我已经足够清楚了

【讨论】:

你找到解决方案了吗? 3 年没有答案?奇怪,这个需要回答

以上是关于passport.js 中的本地和 Google 策略:序列化用户时的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 passport.js 将本地策略连接到另一个(Facebook、Twitter、Google 等)

需要了解passport.js本地策略

使用 Node Passport 和 Google Auth 限制登录到特定域

如何正确使用 Passport.js?

Passport.js 在 nginx 上表达 google oauth 502 Bad Gateway

向 passport.js 本地策略添加其他字段