【问题标题】:Why does Passport retry the authentication when it fails to connect?为什么 Passport 在连接失败时会重试身份验证?
【发布时间】:2018-12-04 14:41:49
【问题描述】:

我有一个 Node.js & Express 应用,使用 Passportpassport-ldapauth 进行 LDAP 身份验证。

一切正常...除非它无法连接到 LDAP 服务器(它可能处于脱机状态,或者 IP 地址错误等)。在这种情况下,passport.authenticate 以某种方式被执行了两次(我只是不知道为什么),结果,我得到了Error: Can't set headers after they are sent

这些是我的 server.js 和 routes.js 的相关部分:

// Import modules
var express      = require('express');
var session      = require('express-session');
var passport     = require('passport');
var passportLdap = require('passport-ldapauth');

// Configure Express, session suppport, and Passport
var app = express();
app.use(session({ resave: false, saveUninitialized: false, secret: 'foo' }));
passport.use('ldap', new passportLdap({server: { /* LDAP settings */ }}));
app.use(passport.initialize());
app.use(passport.session());

// Routings
app.get('/login', function(req, res) { res.render('loginForm.ejs'); });
app.post('/login', function(req, res) {
    passport.authenticate('ldap', {session: true}, function(err, user, info) {
        if (err || !user) {
            console.log(err ? 'ERROR' : 'CREDENTIALS');
            res.status(403).render('loginForm.ejs', {message: err || 'Wrong credentials!'});
        } else {
            console.log('SUCCESS');
            res.redirect('/home');
        }
    })(req, res);
});

如果认证成功,控制台只显示SUCCESS

如果用户输入了错误的用户名或密码,它会显示CREDENTIALS,并再次加载登录表单,显示“错误的凭据!”信息。控制台上没有出现错误。

但是,如果 LDAP 服务器关闭,我会在控制台上收到ERROR 两次。 (为什么?!)然后很明显,当它使用相同的响应对象执行第二个res.render 时,我得到了Can't set headers after they are sent 错误。由于这是第二次尝试失败,用户仍然会在表单登录时显示正确的错误消息(在第一次尝试时呈现)。

如果我将 if (err) 块更改为 next(err) 而不是 res.render()... 我没有遇到标题问题,但仍然存在 LDAP 异常(例如“错误:getaddrinfo ENOTFOUND” ) 在控制台上显示两次,就好像 Passport 在第一次尝试后重试一样。

另外,我注意到 ldapauth 中有一个 handleErrorsAsFailures 选项。如果我启用它,那么它会在控制台上显示两次CREDENTIALS 以显示连接问题,如果我实际上输入了错误的凭据,则只会显示一次。

什么可能导致这个问题?

【问题讨论】:

    标签: node.js express passport.js ldapauth


    【解决方案1】:

    作为 (希望是暂时的?) 解决方法,我已将代码更改为:

    if (err || !user) {
        if (!res.headersSent) { // <---------- CHECK TO PREVENT THE ISSUE ---------
            console.log(err ? 'ERROR' : 'CREDENTIALS');
            res.status(403).render('loginForm.ejs', {message: err || 'Wrong credentials!'});
        }
    } else // ...
    

    这可以防止第二次渲染尝试,并避免Can't set headers after they are sent 错误。

    我仍然不知道是什么导致了这种行为,也不知道如何解决它……

    【讨论】:

      【解决方案2】:

      我的解决方法是使用 if-else 语句将路由中的所有代码包装起来:

          if(res.headersSent) {
             return;
          } else {
            *//the rest of the code goes here*
          }
      

      【讨论】:

        猜你喜欢
        • 2020-08-17
        • 1970-01-01
        • 2010-09-12
        • 1970-01-01
        • 1970-01-01
        • 2015-04-24
        • 2021-01-18
        • 1970-01-01
        • 2022-01-24
        相关资源
        最近更新 更多