NodeJS 为什么从Windows Server运行时会收到ERR_HTTP_HEADERS_SENT('set '),而在我的开发机器上运行时却没有?

ig9co6j1  于 2023-08-04  发布在  Node.js
关注(0)|答案(1)|浏览(194)

我正在开发一个Node/Express应用程序,它将使用ActiveDirectory。登录表单将用户名和密码发布到/auth路由,该路由执行AD身份验证,并在req. session中设置一些值。这个块是有问题的函数,它在我的Windows 10 dev机器上工作得很好,但是当我将此代码移动到Windows服务器时,它失败了,并出现下面的错误。

  • 跟进:* 我已经确认,这只是在为所选Active Directory模块使用LDAPS/TLS时出现的问题。我实际上有这个项目的两个版本,使用不同的Active Directory模块。当使用LDAPS/TLS时,它们都有相同的错误ERR_HTTP_HEADERS_SENT。

如果我将它们恢复到非安全连接或从我的开发程序运行它。机器没问题

http_app.post('/auth', function(req, res) {
    
    req.body.username = `${req.body.username}@${APP_DOMAIN}`;

    ad.authenticate(req.body.username, req.body.password, function(err, auth) {
        if (err || !auth) {
            req.session.authenticated = false;
            res.status(401).send(`Login failed, please <a href="/">try again.</a>.<br /><br /><details><summary>Technical</summary>${JSON.stringify(err)}</details>`);
            return;
        } else if (auth) {
            req.session.authenticated = true;
            req.session.userPrincipalName = req.body.username;
            //it fails on either of these lines, but only when running on a Windows Server
            //res.status(200).send(`<a href="/app">Ok!!!</a>`);
            res.redirect('/app');
            return;
        }
    });
});

字符串
当我将所有代码移动到Windows Server进行测试时,在登录过程中出现此错误。据我所知,环境之间没有任何差异,它们使用相同版本的Node,以及所有相同的node_modules文件:

Listening on *:80
(node:3304) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTP
S requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
node:_http_outgoing:649
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:399:5)
    at ServerResponse.setHeader (node:_http_outgoing:649:11)
    at ServerResponse.header (C:\Users\username\Desktop\cet\node_modules\express\lib\response.js:794:10)
    at ServerResponse.send (C:\Users\username\Desktop\cet\node_modules\express\lib\response.js:174:12)
    at file:///C:/Users/username/Desktop/cet/app/server.mjs:350:33
    at Client.handleError (C:\Users\username\Desktop\cet\node_modules\activedirectory\lib\activedirectory.js:1817:14
)
    at Client.emit (node:events:511:28)
    at TLSSocket.onSocketError (C:\Users\username\Desktop\cet\node_modules\ldapjs\lib\client\client.js:1001:12)
    at TLSSocket.emit (node:events:511:28)
    at emitErrorNT (node:internal/streams/destroy:151:8) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

Node.js v20.1.0

gzszwxb4

gzszwxb41#

好了问题解决了
我发现有一个奇怪的因素涉及我的VPN连接,我的组织中没有人可以解释。如果我的开发人员代码工作。计算机已连接到VPN,但在内部部署时无法工作。这里有很多因素在起作用,包括一些时髦的TLS解密我们的信息。团队在网络上做什么。我决定不去管那个小鬼,只专注于如何真正解决这个问题。我做了两件事来解决它:
1.将我们的自签名CA和域证书添加到ActiveDirectory对象。告诉Node盲目地信任连接是行不通的,它总是失败。如果您的组织使用自签名证书,请索取CA链中的证书副本。

//set the global ad value to an ad connection using the saved service account
ad = new ActiveDirectory({
    url: `ldaps://${APP_DOMAIN}:636`,
    baseDN: `${APP_BASEDN}`,
    username: ad_service_account,
    password: ad_service_account_password, 

    //add CA certs here:
    tlsOptions: {
        cert: fs.readFileSync('domain-cert.cer'),
        ca: fs.readFileSync('certificate-authroity-cert.cer'),
    },
});

字符串
1.我重写了auth中间件函数,/auth端点如下所示:

//Middleware function for Express, to update the session with an authenticated flag.

function AuthMiddlewareFun(req, res, next) {
    console.log('AuthMiddlewareFun Timestamp: ' + (new Date().toTimeString()));

    ad.authenticate((`${req.body.username}@${APP_DOMAIN}`), req.body.password, function(err, auth) {
        console.log('AuthMiddlewareFun() Error Check: ' + (new Date().toTimeString()));

        if (err) {
            console.error('AuthMiddlewareFun() error: ', err);
        }

        if (auth) {
            console.log('AuthMiddlewareFun() success: ' + (new Date().toTimeString()));
            req.session.authenticated = true;
            req.session.userPrincipalName = req.body.username;
        }

        return next();
    });
};

http_app.post('/auth', AuthMiddlewareFun, function(req, res, next) {
    if(!req.session.authenticated) {
        return res.redirect(`/fail`);
    }
    return res.redirect(`/app`);
});


我的请求路由仍然发生了一件奇怪的事情,因为AuthMiddlewareFun()每次都会被调用两次,但第二次它会生成错误,我们捕获了它,所以最终它工作了。

相关问题