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

passport's req.isAuthenticated always returning false, even when I hardcode done(null, true)

我正在尝试让我的 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 正在打印。 为什么它不起作用?

我遇到了类似的问题。可能是由于护照所需的快速会话中间件。通过按以下顺序使用中间件修复它:(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());

我遇到了同样的问题,忘记添加

request.login()

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

希望这对其他和我一样最终来到这里的人有所帮助。

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

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

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

对于新手

我遇到了类似的问题,我的 isAuthenticated() 函数会 return false.I 浪费很多时间,希望这个答案可以节省你的时间。

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

  1. 中间件设置顺序 (express-session > pass.initialize > pass.session).
  2. 序列化和反序列化方法需要根据请求传递用户。(有关更多信息,我已经发布了关于此 link.. 的答案)如果没有用户请求,则 isAuthenticated会 return false....并重定向到定义的 PATH ......当 false....
  3. 模型(user.js)中定义的getUserByIdfindById函数需要有一个User.findById (而不是 User.findOne)函数已定义。(此函数会在每个会话中根据请求加载用户)

我通过修复 passport.deserializeUser 解决了这个问题。我使用的是 mongo 本机,并且由于大多数示例使用 Mongoose,我再次陷入了 _id 陷阱。

所以在deserializeUser

中读取用户的时候记得把_id设为mongoObjectID
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,并且没有任何地方指示错误。

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

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

如果你像这样包装你的路线:

module.exports = function(){

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

}

您必须像这样将 "app and passport" 传递给您的路线:

module.exports = function(app,passport){

//routes n stuff

}

我也遇到了同样的问题,但是@PVThomas 给了我解决方案,就像这里的答案一样。 我的问题是 deserialize() 中的 findById() 方法。我在 findById() 中使用 findOne() 然后我用 find() 替换它,现在 req.isAuthenticated() 工作正常。我的应用程序没有保存 req.session.passport.user,它返回 undefined,然后在用 find() 替换 findOne() 后,它将用户 ID 保存在 req.session.passport.user.

即使正在登录,我也遇到了同样的问题。 我犯的错误是在初始化护照之前调用中间件 isLoggedIn。 因此,您编写代码的顺序非常 important.Please 确保顺序以正确的顺序编写。 我是按以下顺序写的

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

我也遇到了同样的问题,在网上找不到任何解决方案,但我想通了。

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 要求和使用应在任何其他使用之前。试试这个我相信这会起作用,对我有用!

passport.js 中有一个怪癖,没有人真正提到,但我发现了。这就是为什么您可以创建一个帐户或登录,它一开始可以很好地进行身份验证,但后来您会发现 req.userundefinedreq.isAuthenticated()false 整个应用程序。

验证后,passport.js 要求您reroute/redirect。 这就是 passport 初始化实际会话的方式。

  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 应用都是如此。

app.use(
    session({
        secret: 'Our little secret.',
        resave: false,
        saveUninitialized: true,
        cookie: { secure: true } << it was extra for me
    })
);

我知道晚了,但我在 FB 登录策略上遇到了这个问题。它工作正常,直到突然停止工作,而且在 Safari 中也是如此。我对上述所有解决方案都一头雾水,但似乎没有任何效果。最后 chrome 网络控制台给出了一个线索,其中它仍然在 chrome 上工作。警告是这样的:

http://www.facebook.com/ 处的跨站点资源关联的 cookie 设置时没有 SameSite 属性。 Chrome 的未来版本将仅在使用 SameSite=NoneSecure.

设置跨站点请求时传送 cookie

直到那时我才意识到我不应该在快速会话中设置 Samesite: true 因为它不会为登录设置 facebook cookie。经过几天的黑客攻击,我通过将 samesite 更改为 "none" 解决了这个问题。

希望对以后遇到此问题的人有所帮助。

我的情况已解决,我也遇到了同样的问题,但只需按如下所述重新排序代码即可解决:

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

之前的代码:

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()
})

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

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

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

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

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

我认为您的错误来自于视图,无论是 ejs、pug 还是 react。您的表单组中没有名称 属性 与传递给 localstrategy 回调函数的参数相对应。 这就是为我修复它的原因。

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

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

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

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

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

如果您使用此代码,请确保按如下方式更改代码,

cookie:{ secure :false}

将 cookie 中的安全密钥设置为 false