我有一个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
来解决连接问题,只有在我输入错误的凭据时才显示一次。
什么可能导致此问题?
答案 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();
});