护照的req.isAuthenticated总是返回false,即使我硬编码完成(null,true)

时间:2015-03-17 23:26:39

标签: node.js express passport.js passport-local

我正在尝试让我的Passport本地策略正常运行。

我已经设置了这个中间件:

passport.use(new LocalStrategy(function(username, password, done) {
    //return done(null, user);
    if (username=='ben' && password=='benny'){
        console.log("Password correct");
        return done(null, true);
    }
    else
        return done(null, false, {message: "Incorrect Login"});
}));

然后在这里

app.use('/admin', adminIsLoggedIn, admin);

function adminIsLoggedIn(req, res, next) {

    // if user is authenticated in the session, carry on 
    if (req.isAuthenticated())
        return next();

    // if they aren't redirect them to the home page
    res.redirect('/');
}

它总是失败并重定向到主页。

我无法弄清楚为什么会这样?为什么不进行身份验证呢?

在我的控制台中,我可以看到Password Correct正在打印。 为什么它不起作用?

19 个答案:

答案 0 :(得分:43)

我有类似的问题。可能是由于护照所需的快速会话中间件。通过按以下顺序使用中间件来修复它:( Express 4)

var session = require('express-session');

// required for passport session
app.use(session({
  secret: 'secrettexthere',
  saveUninitialized: true,
  resave: true,
  // using store session on MongoDB using express-session + connect
  store: new MongoStore({
    url: config.urlMongo,
    collection: 'sessions'
  })
}));

// Init passport authentication 
app.use(passport.initialize());
// persistent login sessions 
app.use(passport.session());

答案 1 :(得分:9)

FOR NEWBIES

我遇到了类似的问题,我的isAuthenticated()函数会返回false。我失去了很多时间,希望这个答案可以保存你的。

需要注意的一些常见问题,

  1. 中间件设置顺序(express-session> pass.initialize> pass.session)(当你这样做时检查你的语法)。
  2. 序列化和反序列化方法需要在请求中传递用户。(有关详细信息,我已在此链接上发布了答案.. Basics of Passport Session (expressjs)-why do we need to serialize and deserialize?)如果没有用户请求,则isAuthenticated将返回false ....并重定向到定义的PATH ......当为false时......又...再次......检查你的语法。
  3. 模型中定义的 getUserById findById 函数(user.js)需要有一个User.findById(而不是User.findOne再次检查你的..等待FOR IT..SYNTAX)函数定义。(此函数将在每个会话中加载用户请求)

答案 2 :(得分:7)

这也可能是您客户的POST / GET电话的问题。我有这个完全相同的问题,但事实证明我必须给fetch(这就是我使用的)选项credentials:'include',如下所示:

fetch('/...', {
  method: 'POST',
  headers: myHeaders,
  credentials: 'include',
  body: ...
  ...})

原因是因为fetch不支持传递cookie,这在这种情况下是必需的。

答案 3 :(得分:4)

我的问题是我将cookie.secure设置为true,即使数据未超过https。

app.use(require('express-session')({
    secret: process.env.sessionSecret,
    cookie: {
        maxAge: 1000 * 60 * 60 * 24 * 7 // 1 week
    },
    store: store,
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false } // Remember to set this
}));

如果您不使用https

,请务必将Cookie设置为false
cookie: { secure: false } // Set to false

此外,如果您确实认为您有https,请记得信任代理

app.set('trust proxy', 1) // trust first proxy

答案 4 :(得分:3)

忘记添加

我遇到了同样的问题
request.login()

on

app.post('/login', 
    function(request, response, next) {
        console.log(request.session)
        passport.authenticate('login', 
        function(err, user, info) {
            if(!user){ response.send(info.message);}
            else{

                request.login(user, function(error) {
                    if (error) return next(error);
                    console.log("Request Login supossedly successful.");
                    return response.send('Login successful');
                });
                //response.send('Login successful');
            }

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

希望这可能对其他人的帮助有所帮助,就像我一样。

答案 5 :(得分:2)

passport.js有一个纽扣,没人真正提到,但我发现了。这就是为什么您可以创建一个帐户或登录并首先对其进行身份验证的原因,但随后在整个应用程序中发现req.userundefinedreq.isAuthenticated()false

通过身份验证后,passport.js要求您重新路由/重定向。这就是通行证初始化实际会话的方式。

  signIn(req, res, next) {
    passport.authenticate("local")(req, res, function() {
      if (!req.user) {
        console.log("User not found!");
      } else {
        res.redirect("/")
        console.log("signed in")
      }
    })
  }

如果您在验证后不重新路由,它甚至都不会启动会话,因为req.user并且req.isAuthenticated()为假。

我的应用程序是React和Node应用程序,但是Node应用程序和React / Node应用程序都是如此。

答案 6 :(得分:1)

我遇到了同样的问题,问题是我使用的浏览器默认阻止了 Cookie。为了解决这个问题,我将我的应用 URL 添加到允许使用 cookie 的边。

答案 7 :(得分:0)

大家好,我想在这里分享我的错误。

app.use(session({
    secret: process.env.SECRET,
    resave: false,
    saveUninitialized: true,
    cookie: { secure: true }    
  })

如果您使用此代码,请确保将代码更改如下,

cookie:{ secure :false}

答案 8 :(得分:0)

我遇到了类似的问题。我通过改变函数调用的顺序来修复它。

// Call session middleware first
expressApp.use(session(....blah))

// Then initialize passport
expressApp.use(passport.initialize());
expressApp.use(passport.session());

答案 9 :(得分:0)

我相信您的错误来自于 ejs、pug 或 react。您的表单组中没有与传递给 localstrategy 回调函数的参数相对应的 name 属性。 这就是为我修复它的原因。

答案 10 :(得分:0)

我必须同意@karan525。但是,我确保在我的应用程序页面上的不同位置测试了我的代码部分。它最终对我有用的地方是在开始时,但在任何配置文件之后。

// Session 
app.use(session({
secret: 'not so secret',
resave: true,
saveUninitialized: true,
}));

// Passport middleware
app.use(passport.initialize());
app.use(passport.session());

答案 11 :(得分:0)

在我看来,我也遇到了同样的问题,但仅通过按如下所述重新排序代码来解决:

// --------------------------------

先前的代码:

app.use(flash())
app.use(session({
    secret: 'somesecret',
    resave: false,
    saveUninitialized: false
}))
// using the custom middleware for storing variable in response
app.use((req, res, next) => {
    res.locals.isAuthenticated = req.isAuthenticated()
    next()
})
app.use(passport.initialize())
app.use(passport.session())

// --------------------------------

重构代码:(已解决问题):

app.use(flash())
app.use(session({
    secret: 'somesecret',
    resave: false,
    saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())

// using the custom middleware for storing variable in response
app.use((req, res, next) => {
    res.locals.isAuthenticated = req.isAuthenticated()
    next()
})

// --------------------------------

答案 12 :(得分:0)

我知道已经很晚了,但是我在FB登录策略上遇到了这个问题。它工作正常,直到突然停止工作,这也只在Safari中停止。我对上述所有解决方案都束手无策,似乎没有任何效果。最终,Chrome Web控制台给出了一个线索,然后仍然可以在chrome上运行。警告是这样的:

设置了与http://www.facebook.com/处的跨站点资源关联的cookie,而没有SameSite属性。如果将来的Chrome浏览器版本设置为SameSite=NoneSecure,则只会提供带有跨站点请求的cookie。

然后,我才意识到我不应该在快速会话中设置Samesite:true,因为它不会设置用于登录的facebook cookie。经过数天的黑客攻击,我通过将同一站点更改为“无”来解决此问题。

希望它对将来遇到此问题的人有所帮助。

答案 13 :(得分:0)

app.use( 会话({ 秘密:“我们的小秘密。”, 重新保存:错误, saveUninitialized:是的, cookie:{安全:真} <<对我来说这是额外的 }) );

答案 14 :(得分:0)

我也有同样的问题,在网络上找不到任何解决方案,但我发现了。

app.use(require("express-session")({
secret: "This is the secret line",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({extended: true}));

express-session要求和使用应先于其他用途。试试这个,我相信这会工作,为我工作!!

答案 15 :(得分:0)

即使正在登录,我也面临同样的问题。 在初始化护照之前,我所做的错误是调用中间件isLoggedIn。 因此,编写代码的顺序非常重要,请确保顺序正确。 我按以下顺序写过

app.use(require('express-session')({
    secret:'short' ,
    resave:false,
  saveUninitialized:false,
  cookie:{secure:false}
}))
app.use(passport.initialize())
app.use(passport.session())
passport.use(new localstrategy(function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      if (user.password!=password) { return done(null, false); }
      return done(null, user);
    });
  }
))
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())
app.use(isLoggedIn); 

答案 16 :(得分:0)

我也面临着同样的问题,但是@PVThomas为我提供了解决方案,如“答案”中的此处。 我的问题是findById()中的deserialize()方法。我在findOne()中使用了findById(),然后将其替换为find(),现在req.isAuthenticated()可以正常工作。我的应用没有保存req.session.passport.user,返回的是 undefined ,然后将findOne()替换为find()后,它在req.session.passport.user中保存了用户ID。

答案 17 :(得分:0)

如果您像这样包裹路线:

module.exports = function(){

router.get('/',(req,res)=>{
 res.send('stuff');
  }

}

您必须像这样将“应用和护照”传递到您的路线:

module.exports = function(app,passport){

//routes n stuff

}

答案 18 :(得分:0)

我通过修复 passport.deserializeUser 修复了此问题。我使用的是mongo native,因为大部分的例子都使用了Mongoose,我再一次陷入了_id陷阱。

所以请记住在deserializeUser中读取用户时_id是一个mongo ObjectID

passport.deserializeUser(function(user, done) {
    const collection = db.get().collection('users')
    const userId = new mongo.ObjectID(user);
    collection.findOne({_id : userId}, function(err, user) {
        if (err) done(err, null);
        done(null, user);
    });
});

我的查询没有找到用户,因为我没有将id设为ObjectID,并且没有任何错误显示在任何地方。