【问题标题】:Active Directory authentication with NodeJS使用 NodeJS 进行 Active Directory 身份验证
【发布时间】:2018-11-10 09:04:33
【问题描述】:

我正在尝试构建一个 NodeJS 服务器并计划使用组织的 Microsoft Active Directory 进行身份验证。

我对许多包(activedirectory、activedirectory2、ldapjs 等)都进行了同样的尝试

但它们似乎都不适合我。

我提供的是 LDAP URL,下面是我的代码。

var ldapjs = require('ldapjs');

var config = { url: 'ldap://mycompany.com/dc=mycompany,dc=com'
           ,timeout: 10
           ,reconnect: {
              "initialDelay": 100,
              "maxDelay": 500,
              "failAfter": 5
              } 
        }

var username = "user_id@mycompany.com";
var password="password";

const ldapClient = ldapjs.createClient(config);


ldapClient.bind(username, password, function (err) {
console.log("Logging data...");
ldapClient.search('dc=mycompany,dc=com', function (err, search) {
 if (err) {
    console.log('ERROR: ' +JSON.stringify(err));
    return;
  }
search.on('searchEntry', function (err,entry) {
   if (err) {
    console.log('ERROR: ' +JSON.stringify(err));
    return;
  }
  else{
    var user = entry.object;
    console.log("Done.");
    return;
   }

   });
  });
});

有时它可以工作,但在大多数情况下,我不断收到以下错误(可能是当它选择不同的 IP 时)

Error: connect ETIMEDOUT <ip address>:389
at Object.exports._errnoException (util.js:1018:11)
at exports._exceptionWithHostPort (util.js:1041:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)

让我困惑的是;如果我在我的 C# 应用程序中尝试使用相同的 LDAP URL,它可以正常工作。

.Net 应用程序使用它的方式与 NodeJS 使用的方式有区别吗?

我可以通过某种方式更改我的代码以使其正常工作吗?

【问题讨论】:

    标签: node.js active-directory


    【解决方案1】:

    由于这是谷歌搜索结果中弹出的第一个问题,而且我花了很长时间才弄清楚如何使用 Active Directory Authentication,所以我将分享This教程中的解决方案。

    与我在互联网上找到的其他示例相比,它非常容易理解和实施:

    npm install --save activedirectory

    // Initialize
    var ActiveDirectory = require('activedirectory');
    var config = {
        url: 'ldap://dc.domain.com',
        baseDN: 'dc=domain,dc=com'
    };
    var ad = new ActiveDirectory(config);
    var username = 'john.smith@domain.com';
    var password = 'password';
    // Authenticate
    ad.authenticate(username, password, function(err, auth) {
        if (err) {
            console.log('ERROR: '+JSON.stringify(err));
            return;
        }
        if (auth) {
            console.log('Authenticated!');
        }
        else {
            console.log('Authentication failed!');
        }
    });
    

    最困难的部分是弄清楚用户名使用什么后缀。

    我收到了错误:

    错误:{“lde_message”:“80090308:LdapErr:DSID-0C090400,评论: AcceptSecurityContext 错误,数据 52e,v1db1\u0000","lde_dn":null}

    在最终设置正确的后缀之前,对我来说是这样的:
    var username = 'john.smith@foo.companyname.com

    【讨论】:

    • 嗨,亚历克斯。您的代码中的用户名和密码是什么?用户名和密码由被认证的用户提供还是其他?
    • @HimanshuSingh 是的,用户提供的用户名和密码。在我的代码中,它看起来像这样:exports.login = (username, password, next) =&gt; {ad.authenticate(username + "@,my.company.com", password, (err, auth) =&gt; {...
    • 嗯.. 我想知道它是否可以说是 SSO。我在使用 AD 设置 SSO 时的理解和期望完全不同。如果我的应用程序的用户必须再次传递用户名和密码,那么我不确定这是否可以算作 SSO。您能否看看我发布的问题并给我一些见解? *.com/questions/65936881/… 非常感谢您的帮助:)
    • 抱歉,不知道如何帮助您。此处提供的答案仅回答“您如何通过 AD 服务验证 AD 用户名+密码”的问题
    • 这对我有用。 ldap url中的IP地址也足够了。 var config = { url: 'ldap://ip 地址' }; var username = 'username@domain.local'; var 密码 = '密码';
    【解决方案2】:

    我首先通过npm:express-ntlm 获取发出请求的用户名来完成这项工作。然后使用此信息,我使用npm:activedirectory 查询 Active Directory 以获取该用户的详细信息。

    app.use(
      ntlm({
        domain: process.env.DOMAIN,
        domaincontroller: process.env.DOMAINCONTROLLER
      })
    );
    
    ...
    
    app.use("/", authenticate, require("./routes/index"));
    

    在我的身份验证中间件中,我现在可以访问包含

    的 req.ntlm
    { DomainName: '...',
      UserName: '...',
      Workstation: '...',
      Authenticated: true }
    

    我设置了 ActiveDirectory 对象,并注意“bindDN”和“bindCredentials”而不是“用户名”和“密码”:

    var ad = new ActiveDirectory({
      url: process.env.DOMAINCONTROLLER,
      baseDN: process.env.BASEDN,
      bindDN: process.env.USERNAME,
      bindCredentials: process.env.PASSWORD
    });
    

    然后您可以像在 npm:activedirectory 文档中一样使用广告对象:

    ad.findUser(req.ntlm.UserName, (err, adUser) => {
        ...
    });
    

    findUser 返回诸如名字和姓氏、电子邮件地址之类的东西,这是我所需要的,但您可以轻松查看组。

    【讨论】:

    • 可能想指出绑定用户不是登录的用户,而是有权限进行所需成员资格查询的服务用户。
    • 即使这在今天仍被认为是易受攻击的,oauth / saml 将提供更好的安全性。
    【解决方案3】:

    配置对象指定 10 毫秒超时。这似乎很短。你打算暂停 10 秒吗?

    JS Documentation

    您是否在 C# 中使用 LdapConnection.Timeout 对象?那个需要几秒钟。

    C# Documentation

    【讨论】:

      【解决方案4】:

      我怀疑您遇到的情况是 Active Directory (AD) 具有高可用性,并且并非始终 100% 的域控制器都在线。 C#似乎有一些方法可以检测哪些可能不在线?

      在为域使用 HA 名称时,我也有过类似的经历。

      在这些情况下,与您的 AD 管理员交谈并获取应该为您的服务器所在站点提供服务的 AD 服务器并通过 IP 地址或 DNS 直接与该服务器交谈会有所帮助。

      希望对您有所帮助。

      【讨论】:

        最近更新 更多