PassportJS deserializeUser从未调用过

时间:2012-06-30 21:22:21

标签: node.js session passport.js

我已经设置了Passport来验证存储在mongodb中的用户。似乎工作正常:身份验证成功/失败,会话变量设置。但是,让Passport检查会话是否失败。我添加到deserializeUser回调中的console.log语句从来没有看到过光明的事情,这似乎是完全错误的。我认为我的问题与deserializeUser从未被调用有关。有人能够诊断我的错误吗?

// Passport configuration
passport.serializeUser(function(user, cb){ cb(null, user.id) });
passport.deserializeUser(function(uid, cb){
  console.log("Trying to deserialize user: "+uid);
  User.findById(uid, function(err, user){
    cb(err, user);
  });
});
// auth strategy function
passport.use(new LocalStrategy({usernameField: 'email'},
  function(email, pass, done){
    User.findOne({email: email}, function (err, user) {
      if (err)
        return done(err);
      if (!user)
        return done(null, false, {message: "Couldn't find user"});
      var crypted = bcrypt.hashSync(pass, user.salt);
      if(user.hashpass != crypted)
        return done(null, false, {message: "Bad password"});
      return done(null, user);
    });
  }
));

passport.CreateSession =  function (req, res, next) {
  passport.authenticate('local', function(err, user, info){
    if(err || !user)
      return res.json({status: "Failure: "+err});
    req.logIn(user, function (err){
      if(err)
        return res.json({status: "Failure: "+err});
      return res.json({status: "Authenticated"});
    });
  })(req, res, next);
};

在app.js中有以下内容:

app.post('/session', passport.CreateSession); // restify better
app.del('/session', passport.DestroySession);
app.get('/images', passport.CheckSession, routes.images);

12 个答案:

答案 0 :(得分:35)

对于遇到此问题的其他人,请看一下:

app.use(session({ 
    secret: 'something', 
    cookie: { 
        secure: true
    }}));

如果您将cookie.secure设置为true并且您不使用SSL(即https协议),那么具有会话ID的cookie不会返回到浏览器,并且所有内容都会无声地失败。删除此标志为我解决了问题 - 需要花费数小时才能实现这一点!

答案 1 :(得分:25)

如果在使用护照进行身份验证时使用authenticate回调,则需要手动登录用户。不会为你打电话。

passport.authenticate('local', function (err, user) {
    req.logIn(user, function (err) { // <-- Log user in
       return res.redirect('/'); 
    });
})(req, res);

答案 2 :(得分:11)

您有use()'d passport.session()中间件吗?就像在这个例子中一样:

https://github.com/jaredhanson/passport-local/blob/v1.0.0/examples/login/app.js#L91

这就是恢复会话并调用deserializeUser的原因,所以听起来可能会丢失。

答案 3 :(得分:2)

好的,这花了我近3天的时间来解决,这似乎很简单,至少就我而言。在调用以下命令之前,我必须先放置app.use(require('cookie-parser'));app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));

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

注意:这些代码段不是我的实际代码,我从https://github.com/passport/express-4.x-local-example> server.js文件中获取了这些代码段;但这就是要点。

答案 4 :(得分:1)

我整天都在解决同样的问题。我有一个自定义回调设置来执行授权(如http://passportjs.org/guide/authenticate/的底部)。看起来Passport在处理其他中间件之前预处理了所有请求对象(基于我写的一些日志语句)。作为预处理的一部分,它将反序列化的用户信息放入request.user对象中。不幸的是,passport.authenticate(&#39; local&#39;,回调)的默认行为似乎是忽略任何会话或cookie数据,而是假设在请求对象中发送用户名和PW。我所做的是首先检查request.user对象,如果它存在,则意味着Passport已完成预处理,然后我可以直接调用login。这是我的授权功能,我用它来代替passport.authenticate(&#39; local&#39;):

function doAuth(request, response, next)
{ 

if (request.user) {
    request.logIn(request.user, function (err) {
        if (err) {
            console.log(err);
            response.status(500).json({message:
                    "Login failed. Auth worked. Nonsense"});
            return;
        }
        console.log("doAuth: Everything worked.");
        next();
    });
    return;
}

passport.authenticate('local', function(err, user, info) {
    if (err) {
        response.status(500).json({message: "Boo Passport!"});
        return; //go no further
        //until I figure out what errors can get thrown
    }
    if (user === false) {
        console.log("Authentication failed. Here is my error:");
        console.log(err);
        console.log("Here is my info:");
        console.log(info);
        response.status(500).json({message: "Authentication failed."});
        return;
    }
    request.logIn(user, function(err) {
        if (err) {
        console.log("Login failed. This is the error message:");
        console.log(err);
        response.status(500).json({message:"Login failed."});
            return;
        }
        console.log("doAuth: Everything worked. I don't believe it.");

        next();
    });
})(request, response, next);

 }

答案 5 :(得分:0)

在我的情况下,这是因为我有以下代码:

app.get("/auth/google/callback", 
    passport.authenticate("google", { 
        failureRedirect: "/admin/login/?error",
    }),
    (req, res) => {
        return res.redirect("/admin/");
    },
);

显然,在这种情况下,不会调用req.login()(它将调用反序列化)。我将其更改为此并奏效了:

app.get("/auth/google/callback", 
    passport.authenticate("google", { 
        successRedirect: "/admin/", 
        failureRedirect: "/admin/login/?error",
    })
);

答案 6 :(得分:0)

在我的情况下,我放置了

app.use(cookieSession({
  maxAge : 60*60*1000,
  keys : [key.cookieSession.key1]
}));

上方

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

它奏效了。

答案 7 :(得分:0)

我通过网络安全性或开放隐身模式打开了谷歌浏览器,对我来说很有效

web-security for linux /usr/bin/google-chrome-stable
--disable-web-security --user-data-dir=/home/jossnaz/.config/google-chrome/

答案 8 :(得分:0)

Heroku 中,所有请求都以纯http形式进入应用程序,但是带有X-Forwarded-Proto标头以了解原始请求是http还是https。

这会导致Express看到非SSL流量,因此在Heroku上运行时拒绝设置安全cookie。您必须通过设置“信任代理”来告诉express信任该标头中的信息。

app.set('trust proxy', 1);

就在

之前
app.use(session...

如果您在Heroku上遇到麻烦,可以为您工作。如果您的Cookie /会话混乱了,那可能就是为什么不调用反序列化的原因。

答案 9 :(得分:-1)

确保代码行app.use(express.static(path.join(__dirname, 'public')));低于app.use(require('express-session')

答案 10 :(得分:-1)

你必须先配置 session,然后在 configinitialize() 和 session() 之后配置

// config session first 
app.use(session({ 
    secret: 'something', 
    cookie: { 
        secure: true
    }}));
// after configinitialize() and session()
app.use(passport.initialize())
app.use(passport.session())

答案 11 :(得分:-3)

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

passport.deserializeUser(
    function(id, done){
        User.findById(id, function(err, user){
            if(err){
                done(err);
            }
            done(null, user);
        });
});

**> try this one**