You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js生产环境中ldap.js的res.on('searchEntry')无返回结果求助

问题原因分析

开发模式正常但生产模式下LDAP搜索停滞,核心是这几个代码问题:

1. call函数未正确返回Promise

原call是异步函数,但内部没有返回top函数的Promise,导致await call(...)实际拿到的是undefined。开发模式下可能因事件循环的侥幸未暴露问题,生产模式下Next.js的编译优化直接放大了这个隐性错误。

2. 全局LDAP Client引发请求冲突

使用全局client变量,生产模式下多请求会复用同一个连接,并发时搜索操作的事件监听会被覆盖或丢失,直接导致搜索流程卡住。

3. login函数返回未定义变量

原代码中return user;的user变量未定义,Next.js Auth无法获取有效用户信息,引发后续流程异常。

4. 搜索属性配置为空数组

getUserDetails里attributes: []会让LDAP服务器不返回任何用户属性,开发模式下可能因服务器配置宽松还能返回默认属性,生产模式下就无法触发searchEntry事件。


修复步骤

1. 修正call函数的Promise返回

直接返回top函数的Promise即可:

const call = async (user, password) => {
  return top(user, password);
};
// 简化写法:
// const call = (user, password) => top(user, password);

2. 移除全局Client,每个请求使用独立连接

将全局client改为局部变量,在ADLoginUserCheck中创建客户端并传递给getUserDetails,避免请求间的连接冲突:

const ADLoginUserCheck = async (user, password) => {
  return new Promise((resolve, reject) => {
    const client = createClient(); // 每个请求创建独立客户端
    // 注意:bind的DN格式需正确,应为用户UPN(如user@your-domain.com)或完整LDAP DN
    client.bind(`${user}${process.env.USER_SUFFIX}`, password, (err, auth) => {
      if (err) {
        console.log("Reject error...");
        client.destroy();
        reject(err);
      } else {
        console.log("all ok...");
        resolve({ client }); // 将客户端传递给后续搜索逻辑
      }
    });
  });
};

const getUserDetails = async (client, user) => {
  const opts = {
    filter: `(sAMAccountName=${user})`,
    scope: "sub",
    attributes: ["*"] // 指定获取所有属性,或按需列出需要的属性
  };
  return new Promise((resolve, reject) => {
    let userData;
    // 搜索基准DN需正确配置(如OU=Users,DC=your-domain,DC=com),勿直接使用LDAP服务器地址
    client.search(`${process.env.SEARCH_BASE_DN}`, opts, (err, res) => {
      if (err) {
        console.log("Error in search:", err);
        client.destroy();
        reject(err);
      } else {
        res.on("searchEntry", (entry) => {
          console.log("68", entry.pojo.attributes);
          userData = entry.pojo.attributes;
        });
        res.on("error", (err) => {
          console.log("75", err);
          client.destroy();
          reject(err);
        });
        res.on("end", (result) => {
          console.log("userDAta", userData);
          resolve({ userData });
          client.destroy();
        });
      }
    });
  });
};

const top = async (user, password) => {
  const { client } = await ADLoginUserCheck(user, password);
  const userDetails = await getUserDetails(client, user);
  return userDetails;
};

重点提醒:拆分环境变量配置,LDAP服务器地址用process.env.LDAP_URL,用户后缀用process.env.USER_SUFFIX,搜索基准DN用process.env.SEARCH_BASE_DN,避免之前的错误拼接。

3. 修复login函数的返回值

将未定义的user改为实际获取的userInfo:

const login = async (credentials) => {
  try {
    const userInfo = await call(credentials.username, credentials.password);
    console.log(userInfo);

    return userInfo; // 返回正确的用户信息
  } catch (error) {
    console.log("error in login function", error);
    throw new Error("Failed to login");
  }
};

4. 添加LDAP操作超时处理

创建客户端时添加超时配置,避免生产环境因网络问题导致搜索长期停滞:

const createClient = () =>
  ldap.createClient({
    url: process.env.LDAP_URL,
    tlsOptions: { rejectUnauthorized: false },
    reconnect: true,
    timeout: 10000, // 10秒超时
    connectTimeout: 10000
  });

额外检查项

  • 确认生产环境的环境变量配置正确,特别是LDAP地址、搜索DN、用户后缀等参数。
  • 检查生产服务器与LDAP服务器的网络连通性,确保389/636端口开放。
  • 确保用于绑定的LDAP用户拥有搜索用户信息的权限。

内容的提问来源于stack exchange,提问作者Pavel_Bu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 13:37:03