【问题标题】:How to bind to AD server in PHP with credentials from trusted domain?如何使用来自受信任域的凭据绑定到 PHP 中的 AD 服务器?
【发布时间】:2011-09-30 09:10:37
【问题描述】:

我们有多个 AD 服务器,它们之间建立了林信任,因此来自不同域的 Windows 用户能够访问受限资源。假设我们有 domainA.com 和 domainB.com,那么来自域 domainB.com 的任何用户都可以登录到 domainA.com 上的资源。出于安全原因,管理员已禁用对 LDAP 服务器的匿名访问。

现在我们需要在 OpenLDAP 客户端的帮助下,在 PHP 代码中列出来自所有 LDAP 服务器的所有用户。下面是从 domainB.com 获取所有用户信息的 PHP 代码

define('USER', 'user@domainA.com'); // User from domainA.com here
$ldap = ldap_connect('domainB.com') or die('Bad connection');
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_bind($ldap, USER, PASS) or die('Cannot bind');

我的脚本因 ldap 错误“49 无效凭据”消息“无法绑定”而终止。来自 AD 的附加信息:
80090308:LdapErr:DSID-0C0903A9,注释:AcceptSecurityContext 错误,数据 52e,v1db1

我认为问题出在简单的身份验证机制上,因为当我在 Ldap Administrator 客户端中使用 GSS 协商身份验证时,使用与 user@domainA.com 相同的凭据,一切正常。

如何使用来自 user@domainA.com 的凭据在 domainB.com 上成功绑定?

UPD1 使用 SASL DIGEST-MD5 进行身份验证

ldap_sasl_bind ( $ldap, '', $pass, 'DIGEST-MD5', null, 'user@domainA.com');

来自 AD 的日志:

计算机尝试验证帐户的凭据。 身份验证包:WDigest 登录账号:用户 源工作站:DOMAINA 错误代码:0xc000006a 帐户无法登录。 主题: 安全 ID:空 SID 帐户名称: - 帐户域:- 登录 ID:0x0 登录类型:3 登录失败的帐户: 安全 ID:空 SID 账户名:user@domainA.com 账户域名:domainA.com 故障信息: 失败原因:登录时出错。 状态:0xc000006d 子状态:0xc000006d 处理信息: 调用方进程 ID:0x0 调用者进程名称:- 网络信息: 工作站名称:- 源网络地址: 源端口: 详细的认证信息: 登录过程:WDIGEST 身份验证包:WDigest 过境服务:- 包名称(仅限 NTLM):- 密钥长度:0 当登录请求失败时会生成此事件。它是在尝试访问的计算机上生成的。 主题字段指示请求登录的本地系统上的帐户。这通常是服务器服务等服务,或 Winlogon.exe 或 Services.exe 等本地进程。 登录类型字段指示所请求的登录类型。最常见的类型是 2(交互式)和 3(网络)。 进程信息字段指示系统上的哪个帐户和进程请求登录。 网络信息字段指示远程登录请求的来源。工作站名称并非始终可用,在某些情况下可能留空。 身份验证信息字段提供有关此特定登录请求的详细信息。 - 中转服务指示哪些中间服务参与了此登录请求。 - 包名称表示在 NTLM 协议中使用了哪个子协议。

【问题讨论】:

    标签: php authentication active-directory ldap trust


    【解决方案1】:

    我在配置 Moodle 时遇到了这个问题,它使用 PHP LDAP 库和 OpenLDAP 连接到 AD 服务器。解决方案非常简单,是两件事之一(实际上只是归结为一件事):

    1. 使用无范围的用户名(即用户名后没有“@example.com”)
    2. 使用域\用户名

    基本上,它归结为的一件事是获得正确的、预期的用户名语法。我认为这取决于特定的 AD 配置,因为我在各种 AD 服务器上看到了四种有效的用户名:完整 DN、范围用户名(即看起来像电子邮件地址)、域\用户名和普通用户名。

    【讨论】:

    • 我认为这里的选项 2 是最好的。该格式为specifically used,表示用于身份验证的用户和域。
    • 第二个选项在 Windows 7 中对我有用,在 Control Panel\User Accounts\User Accounts > Manage User Accounts 中可以找到域和用户名(在“用户帐户”窗口的“用户”选项卡中)
    【解决方案2】:

    当您在ldap_bind 中指定用户时,您可以尝试将您的用户DN 像这样:

    $bind = ldap_bind($resource, 'cn=jpb,cn=users,dc=dom,dc=fr', '***'); 
    

    另一件事,在您的“Active-Directory Forest”中,您有一个或多个支持名为“全局目录”(GC)的目录的域控制器。 GC 包含林中所有目录的所有对象。


    已编辑 您可以尝试使用 SASL 进行绑定

    $ldap = ldap_connect('domainB.com');
    ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); 
    ldap_sasl_bind ( $conn, NULL,"password",'DIGEST-MD5',NULL,'user@domainA.com',NULL);
    

    【讨论】:

    • 我尝试与我的用户 DN "CN=user, OU=Special Users, DC=domainA, DC=com" 绑定,答案是“无效凭据”。全局目录很有趣,但对我也不起作用。
    • 使用简单绑定,你必须绑定一个DomainB目录的用户!您必须使用 SALS 与 DomainA 用户绑定
    • PHP 中有用于 SASL 绑定的 ldap_sasl_bind() 函数,但我找不到任何好的示例如何进行 Kerberos 或 NTLM 身份验证。你有使用 PHP 代码进行 SASL 身份验证的经验吗?
    • 我很感谢你!今天我将尝试使用 SASL-LDAP 构建 PHP 并检查 SASL 身份验证。我希望一切都会变得正常。
    • 我已经使用 SASL 构建了 PHP,并尝试使用 DIGEST-MD5 进行身份验证,但结果仍然是否定的。我编辑了 DIGEST-MD5 身份验证的问题并添加了一些来自 AD 的日志。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多