43

我已经设置了 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);
4

12 回答 12

43

对于遇到此问题的其他任何人,请查看以下内容:

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

如果您已cookie.secure设置为 true 并且您没有使用 SSL(即 https 协议),则带有会话 ID 的 cookie 不会返回到浏览器,并且一切都会以静默方式失败。删除这个标志为我解决了这个问题——我花了几个小时才意识到这一点!

于 2014-04-16T20:20:57.687 回答
29

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

passport.authenticate('local', function (err, user) {
    req.logIn(user, function (err) { // <-- Log user in
       return res.redirect('/'); 
    });
})(req, res);
于 2016-02-14T05:06:42.130 回答
13

你有没有use()中间件passport.session()?就像在这个例子中一样:

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

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

于 2012-06-30T21:29:02.797 回答
7

好的,这花了我将近 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());

注意:这些片段不是我的实际代码,我是从GitHub获取的,但这就是它的要点。

于 2018-11-08T03:10:55.807 回答
3

就我而言,这是因为我有以下代码:

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",
    })
);
于 2019-05-27T12:43:47.030 回答
1

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

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

 }
于 2014-11-15T08:06:06.270 回答
1

今天我遇到了同样的问题,就我而言,原因是客户端如何进行 API 调用。以下方法帮助我克服了这个问题:

const doFetch(url, method = 'GET', body) {
  const headers = new Headers();
  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');
  headers.append('Cache', 'no-cache');
  const params = { 
    method, headers, 
    credentials: 'include' // The cookie must be sent!
  }
  if(body) {
    params.body = body;
  }
  return fetch(url, params);
}

在此之后,deserializeUser开始被正确调用。

于 2017-11-27T23:00:24.677 回答
0

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

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

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

就在之前

app.use(session...

如果您在 Heroku 上遇到此问题,可能对您有用。如果您的 cookie/会话搞砸了,那么这可能就是不调用反序列化的原因。

于 2020-08-22T04:10:05.890 回答
0

我用网络安全打开谷歌浏览器或打开隐身模式,它对我有用

web-security for linux /usr/bin/google-chrome-stable
--disable-web-security --user-data-dir=/home/jossnaz/.config/google-chrome/
于 2020-06-28T13:27:25.730 回答
0

就我而言,我已经放置

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

以上

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

它奏效了。

于 2019-07-13T09:17:49.540 回答
-1

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

于 2017-06-16T13:07:46.683 回答
-4
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**
于 2013-12-02T10:04:25.837 回答