Почему Passport повторяет аутентификацию, если не удается подключиться? - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть приложение Node.js & Express, использующее Passport и passport-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 дважды для проблем с соединением и только один раз, если я действительно введу неправильные учетные данные.

Что может быть причиной этой проблемы?

1 Ответ

0 голосов
/ 07 декабря 2018

В качестве (возможно, временного?) временного решения я изменил свой код следующим образом:

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.

Я до сих пор не имею ни малейшего представления о том, что вызывает это поведение или как его исправить, хотя ...

...