req.user 注册后未定义

Posted

技术标签:

【中文标题】req.user 注册后未定义【英文标题】:req.user is undefined after sign up 【发布时间】:2017-06-13 22:18:21 【问题描述】:

我不明白为什么注册后req.userundefined 但登录时却没有。我以为我在登录时做了几乎相同的事情。

在我注册后,我在数据库中获取用户,然后对req.user 进行 json 处理,它返回 null。

我的最终目标是在注册后重定向到/ 路由。在/ 路由中,我想测试一下 req.user 是否不为空,并给出有关用户是否经过身份验证的适当消息。

const express = require("express");
const ejs = require("ejs")
const bodyParser = require("body-parser");
// const multer = require("multer");
const mongoose = require("mongoose");
const app = express();

const User = require("./database/models/user");


const port = process.env.port || 3000;

/**********Express session*********/
const expressSession = require("express-session");
/**********************************/
const passport = require("passport");
const localStrategy = require("passport-local").Strategy;

mongoose.connect("mongodb://localhost/passport-ajax");
//Make sure capital P for promise.
mongoose.Promise = global.Promise;



app.use(bodyParser.urlencoded(extended : true));
app.use(bodyParser.json());
// app.use(multer(dest : "./uploads"));

app.use(expressSession(
    secret : "longString",
    resave:false,
     saveUninitialized: false
))



/********************Configure passport*************************/


passport.use("login",  new localStrategy(
    usernameField : "emailOrUsername",
    passwordField : "password",
    passReqToCallback : true
,
    function(req, username, password, done)
        console.log("HIT HERE");
        User.findOne(emailOrUsername: username)
            .then((user)=>
                console.log("FINDING!!");
                if(!user)
                    console.log("My error: NO SUCH USER");
                    return done(null, false, "No such user");
                
                if(password !== user.password)
                    console.log(`Password Doesnt Match`);
                    done(null, false , "Passwords dont match");
                
                console.log("USER MATCHED!!");
                done(null, user)

            )
            .catch((err) => console.log(err));
    
))

passport.use("signUp", new localStrategy(
    usernameField : "emailOrUsername",
    passwordField : "password",
    passReqToCallback : true
,
    function(req, username, password, done)
        // Removing from the DB first so there won't be multiple records while testing.
        User.remove()
        .then(() =>
            User.findOne(emailOrUsername : username)
                .then((user) => 
                    console.log("FINDING INSIDE SIGNUP");
                    if(user)
                        return done(null, false, "User "+ username + "allready exists. " );
                    
                    var user = 
                        emailOrUsername : username,
                        password : password
                    ;
                    new User(user).save()
                        //possible do done(err)
                        .then((newUser) =>
                            if(!newUser) return done("Failed On Create User");
                            done(null, user)
                        )
                )
        )
        .catch((err) => 
            console.log(err);
        )
    
))

function verifyAuth(req, res, next)
    if(!req.isAuthenticated())
        return res.status(401).json(
            err : "Please login correctly. You received a 401 error.",
            sesstionId : req.session.id
        )
    
    next();

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function(user, done)
    done(null, user.id);
);

passport.deserializeUser(function(id, done)
    User.findById(id, function(err, user)
        done(err,user);
    )
)

/**************************************************************/


app.set("view engine", "ejs");

//file will be served like http://localhost:4000/style.css
app.use(express.static(__dirname + "/public"));

app.get("/", (req, res) => 
    console.log("req.user : ", req.user);
    console.log("session: ", req.session);
    const authenticated = req.user ? true : false;
    var query = req.query.message;
    res.render("index", 
        query,
        authenticated
    )
)

app.get("/signUp", (req, res) =>
    res.render("signUp", 
    )
)

app.post("/signUp", (req, res, next) => 
    // console.log(req.body);


    passport.authenticate("signUp", function(err, user, info)
        if(err) console.log(err, " authenticate Signup error! ");
        if(!user) console.log("USER ERROR!");
        req.login(user, function(err) 
            if(err) return err;
            console.log("req.login called!")

            console.log("INFO, " , info)
        )
        // res.redirect("/");
        res.status(201).json(
            user : user,
            session : req.session,
            "req.user" :  req.user // This is null right now.
        );

    )(req, res, next)
, function(err, req, res, next)
    console.log("req.isAuthenticated() >", req.isAuthenticated());
);
app.get("/login", (req,res) =>
    res.render("loginForm");
);

app.post("/login", function(req, res, next)  
    console.log("req.body : ", req.body)
    passport.authenticate("login", function(err, user, info)
        console.log("inside authenticate");
        if(err) console.log(err, " ", req.session.id);
        if(!user) console.log("No user : ", info);
        req.login(user, function(err)  // need this when using custom function
            if(err) console.log(err);
        );
        res.status(201).json(
            user : user,
            session : req.session,
            "req.user" :  req.user
        );
    )(req, res, next); // very import to call this self-executing function
, function(err, req, res, next)
    //possible function here
);

app.get("/unProtected", (req, res) => 
    res.json(
        session : req.session,
        "req.user" : req.user
    )
)
app.get("/protected", verifyAuth, (req, res) =>
    res.json(
        session : req.session,
        "req.user" : req.user
    );
);


app.listen(port, function()
    console.log(`Listening on port $port`);
)

【问题讨论】:

passport.use("signUp", 是干什么用的? 你就是这样使用护照的吧?我相信第一个参数是策略的名称。我相信的函数称为verify 函数。这就是您使用护照制定策略的方式。 对不起,我的意思是;如果您已经定义了/login,为什么还要创建一个单独的? 好问题。我看到很多例子都是这样做的。我试着不这样做,只是使用注册策略存储数据,然后我添加了signup,看看它是否能帮助我解决req.user的问题。 【参考方案1】:

req.login 异步执行,这就是为什么你要传递一个回调函数。所以你应该在这个回调中移动每个响应,这样你就可以给它足够的时间来做它的配置:

req.login(user, function(err) 
  if (err) return err;
  console.log("req.login called!");
  console.log("INFO, ", info);
  return res.status(201).json(
      user: user,
      session: req.session,
      "req.user": req.user
  );
);

同样在 passport.use("signUp"... 中,您应该使用 newUser 调用回调:

var newUser = new User(user);
newUser.save(function(err) 
  if (err) throw err;
  done(null, newUser);
);

并且还使用_id 而不是id 序列化您的用户:

passpost.serializeUser(function(user, done) 
  done(null, user._id);
);

【讨论】:

我之前尝试过类似的方法。我现在会仔细检查是否有帮助。 我把它放进去,现在浏览器挂了。 passport.authenticate("signUp", function(err, user, info) if(err) console.log(err, " authenticate Signup error! "); if(!user) console.log("USER ERROR!"); req.login(user, function(err) if(err) return err; console.log("req.login called!") console.log("INFO, " , info) res.status(201).json( user : user, session : req.session, "req.user" : req.user // This is null right now. ); ) return 回复。 抱歉没有帮助,我也没有看到 console.log("req.login called!"); 被调用。 我相信没有newUser 是我的错误。感谢您的帮助,我真的很感激。我将在其他时间再次检查并关闭问题。【参考方案2】:

我知道它对您的问题的回答很晚。但是现在当我做我的项目时,我遇到了同样的问题。所以我建议你有一个像这样的本地护照策略:

passport.use(new LocalStrategy(
function(username, password, done) 
    console.log(username);
    console.log(password);
    db.collection('user-details').findOne(user_name:username,(err,result)=>
        if(err) done(err);
        if(result.length == 0)
            done(null,false);
        else
        const results = JSON.stringify(result);
        var hash1 = JSON.parse(results);
        var  hash = hash1.password;
        console.log( hash);
        bcrypt.compare(password,hash,function(err,response)
            if(response==true)
                return done(null,user_id:hash1._id);
            else
                return done(null,false);
            
        );
     
   );
 
 ));

并在每个帖子登录和帖子注册中使用此策略。在帖子注册中;像这样将用户名和密码存储到数据库之后

 app.post('register.html',(req,res,next)=>
 //store the username and password into the database
next();
);

记得在 req,res 对象之后使用 next,因为它会将控制权转移到应用程序中的下一个中间件;即在这个 post 方法之后编写的中间件。而旁边的中间件将是passport的本地策略。 像这样使用它:

   app.post('/register.html',passport.authenticate('local',
   successRedirect: '/website.html',
   failureRedirect: '/register.html'
   ));

【讨论】:

以上是关于req.user 注册后未定义的主要内容,如果未能解决你的问题,请参考以下文章

Passport + NodeJs + Express 得到“req.user”未定义

req.isAuthenticated 为 false 且 req.user 未定义。我该如何解决这个问题?

在获取用户时使用 Passport-jwt 时 req.user 未定义

Passport JWT req.user 在我的一条路线中未定义

Node + Express + Passport + Mongoose:req.user 未定义

Passport JS req.user 未定义