为什么Passport无法连接时重试身份验证?

时间:2018-12-04 14:41:50

标签: node.js express passport.js ldapauth

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

一切正常,除非连接到LDAP服务器失败(它可能脱机或IP地址错误等),否则一切正常。在这种情况下,passport.authenticate被执行了两次(我不知道为什么),结果我得到了Error: Can't set headers after they are sent

这些是我的server.js和route.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来解决连接问题,只有在我输入错误的凭据时才显示一次。

什么可能导致此问题?

2 个答案:

答案 0 :(得分:0)

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

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错误。

尽管如此,我仍然不知道是什么原因或如何解决此问题。

答案 1 :(得分:0)

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

document.addEventListener('turbolinks:load', function(){
    $("#ghost_logo").hide();
});