52

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

4

20 回答 20

67

我有一个类似的问题。可能是由于护照所需的快速会话中间件。通过按以下顺序使用中间件来修复它:(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());
于 2015-06-17T04:53:42.293 回答
16

对于新手

我遇到了类似的问题,我的 isAuthenticated() 函数将返回 false。我浪费了很多时间,希望这个答案可以节省您的时间。

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

  1. 中间件设置顺序(express-session > pass.initialize > pass.session)。
  2. 序列化和反序列化方法需要在请求中传递用户。(有关更多信息,我已在此链接上发布了答案。护照会话基础(expressjs)-为什么我们需要序列化和反序列化?)如果没有用户请求然后 isAuthenticated 将返回 false.... 并重定向到定义的 PATH ......当 false....
  3. 模型(user.js)中定义的getUserByIdfindById函数需要定义一个 User.findById(而不是 User.findOne)函数。(此函数将在每个会话中加载用户请求)
于 2017-08-02T08:10:41.470 回答
11

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

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

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

于 2017-06-20T01:28:13.490 回答
11

我的问题是即使数据没有通过 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
于 2018-04-20T23:07:53.073 回答
7

我忘记添加了同样的问题

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

希望这可能会帮助其他与我一样的原因最终来到这里的人。

于 2017-01-11T22:16:34.547 回答
2

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

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

于 2019-05-11T08:07:05.733 回答
2

passport.js 中有一个没有人真正提及的问题,但我发现了。这就是为什么您可以创建一个帐户或登录,并且它最初可以很好地进行身份验证,但后来您会发现整个应用程序req.user中存在undefinedreq.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")
      }
    })
  }

如果您在身份验证后不重新路由,它甚至不会以 a 身份启动您的会话,req.user并且req.isAuthenticated()将是错误的。

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

于 2019-09-01T20:24:52.507 回答
1

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

与跨站点资源关联的 cookiehttp://www.facebook.com/设置为没有该SameSite属性。未来版本的 Chrome 将仅提供带有跨站点请求的 cookie,前提是它们使用SameSite=None和设置Secure

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

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

于 2020-04-29T15:02:49.963 回答
1

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

于 2021-02-25T15:45:00.030 回答
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); 
于 2019-02-11T11:43:54.877 回答
0

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

于 2022-02-05T17:35:03.430 回答
0

我也面临同样的问题,但@PVThomas 给了我解决方案,就像在 Answers 中一样。我的问题findById()在于deserialize(). 我正在使用findOne()infindById()然后我将其替换为find()现在req.isAuthenticated()工作正常。我的应用程序没有保存req.session.passport.user,它返回未定义,然后在替换为findOne()保存find()用户 ID 后req.session.passport.user

于 2018-07-16T18:54:37.783 回答
0
app.use(
    session({
        secret: 'Our little secret.',
        resave: false,
        saveUninitialized: true,
        cookie: { secure: true } << it was extra for me
    })
);
于 2020-03-18T15:05:43.307 回答
0

我相信您的错误来自于 ejs、pug 或 react 的观点。您的表单组中没有 name 属性对应于传递给 localstrategy 回调函数的参数。这就是为我解决的问题。

于 2021-05-01T23:14:34.470 回答
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,并且在任何地方都没有指示错误。

于 2017-11-21T23:43:25.983 回答
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()
})

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

于 2020-05-08T11:32:08.310 回答
0

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

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

// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
于 2021-02-09T17:57:46.880 回答
0

嘿伙计们,我想在这里分享我的错误。

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

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

cookie:{ secure :false}
于 2021-08-10T16:08:52.387 回答
0

我面临着类似的问题。我通过更改函数调用的顺序来修复它。

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

// Then initialize passport
expressApp.use(passport.initialize());
expressApp.use(passport.session());
于 2021-05-20T14:36:23.107 回答
-2

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

module.exports = function(){

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

}

您必须将“应用程序和护照”传递给您的路线,如下所示:

module.exports = function(app,passport){

//routes n stuff

}
于 2018-06-20T04:26:52.083 回答