1

TLDR:passportjspassport-ldapauth 是否存在竞争条件问题?

我在 nodejs 应用程序中使用该koa-passport库和passport-ldapauth策略,旨在针对 AD(Active Directory)对用户进行身份验证。哇,那是一口。

这是我passport.authenticate从 LDAP 中返回的错误:

BusyError: 00002024: LdapErr: DSID-0C060810, comment: No other operations may be performed on the connection while a bind is outstanding.

这里的问题很明显,有一个未完成的绑定,必须先关闭它,然后我才能进行另一个绑定以验证下一个用户。 然而,解决方案不是,它可能与 LDAP 相关,也可能与 passportjs 相关。我在这里希望为后者找到解决方案。(在等待对此#multiprocessing的响应时,将探索 LDAP 的配置选项)

这是我的代码:

import passport from 'koa-passport';
import LdapStrategy from 'passport-ldapauth';
import { readFileSync } from 'fs';
const ldapCert = readFileSync(process.env.LDAP_CERT, 'utf8');

const ldapConfig = {
  server: {
    url: process.env.LDAP_URL,
    bindDN: process.env.LDAP_BINDDN,
    bindCredentials: process.env.LDAP_PASSWORD,
    searchBase: process.env.LDAP_SEARCH_BASE,
    searchFilter: process.env.LDAP_SEARCH_FILTER,
    searchAttributes: ['sAMAccountName'],
    tlsOptions: {
      ca: [ldapCert]
    }
  }
};

module.exports = async (ctx, next) => {
  passport.initialize();
  passport.use(new LdapStrategy(ldapConfig));
  await passport.authenticate('ldapauth', { session: false }, async (err, user, info) => {
    if (err) {
      console.log('Invalid Authentication Error');
      ctx.throw('INVALID_AUTHENTICATION');
    } else if (!user) {
      console.log('Invalid username or password Error');
      ctx.throw('INVALID_USERNAME_PASSWORD');
    } else {
      await next(); // continue to authorization flow
    }
  })(ctx, next);

在我们开始之前,要知道ldapConfigs在应用程序的整个生命周期中所有内容都保持不变,这意味着我在每次查找时都使用相同的 BINDDN 和 PASSWORD

因此,如标题中所述,此错误间歇性地发生。因此,代码本身通常可以正常工作,并且我能够在大约 95% 的时间内对用户进行身份验证,并且如果它INVALID_AUTHENTICATION在密码正确时抛出错误,那就是当我BusyError在日志中获取 the 时。

当我输入虚假的用户名/密码时,这个问题更加突出并且更容易重现,理想情况下应该提示我INVALID_USERNAME_PASSWORD错误,我大约有 75% 的时间。我得到的另外 25% INVALID_AUTHENTICATION

我什至尝试使用ldapsearchtmux. 我使用相同的 binddn 同时在大约 20 个窗格中运行了一个调用,它们都恢复得很好(我应该尝试用更多来运行它吗?100 个?1000 个?)。这就是让我相信问题不在于 LDAP 或 AD 的原因,而更多的是 passportjs。

我得出的结论是,passportJS 可能存在种族条件问题,但我在互联网上找不到任何文献。有没有人遇到过这样的事情?我相信绑定可能没有关闭,因为有时passport.authenticate可能会在调用回调之前返回?这甚至可能吗?它与我如何使用 async/await 进行编码有关吗?

我的后备方案可能是完全抛弃passportjs,只尝试使用ldapjs。任何想法,意见,建议,讨论将不胜感激

如果需要,这是完整的堆栈跟踪:

BusyError: 00002024: LdapErr: DSID-0C060810, comment: No other operations may be performed on the connection while a bind is outstanding., data 0, v3839
    at messageCallback (/app/node_modules/ldapjs/lib/client/client.js:1419:45)
    at Parser.onMessage (/app/node_modules/ldapjs/lib/client/client.js:1089:14)
    at emitOne (events.js:116:13)
    at Parser.emit (events.js:211:7)
    at Parser.write (/app/node_modules/ldapjs/lib/messages/parser.js:111:8)
    at TLSSocket.onData (/app/node_modules/ldapjs/lib/client/client.js:1076:22)
    at emitOne (events.js:116:13)
    at TLSSocket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at TLSSocket.Readable.push (_stream_readable.js:208:10)
    at TLSWrap.onread (net.js:597:20)
InternalServerError: INVALID_AUTHENTICATION
    at Object.throw (/app/node_modules/koa/lib/context.js:97:11)
4

0 回答 0