如何在 php 中使用 LDAP 从 Active Directory 搜索和更新用户数据?

Posted

技术标签:

【中文标题】如何在 php 中使用 LDAP 从 Active Directory 搜索和更新用户数据?【英文标题】:How search and update user data from Active Directory using LDAP in php? 【发布时间】:2018-04-29 03:42:52 【问题描述】:

我使用 php 5.6,并尝试在 php 中通过 LDAP 在 Active Directory 中搜索用户。 示例搜索:

ldap_connect($host, '389');
ldap_search($client, 'DC=shamsa,DC=real,DC=kamchatka,DC=ru', '(&(objectClass=user)(CN=user_name))', '*');

我成功获取用户数据,但返回的字段中不存在 userPassword。我需要用户密码来比较 Active Data 中的密码和用户输入的密码。

我如何从 Active Data 中获取用户密码,或者如何比较用户输入的密码和 Active Directory 中的密码而不获取?

顺便说一句,我还需要更新 Active Directory 中的用户数据。例如更新名称和电子邮件字段。我该怎么做?

感谢您的回答。

【问题讨论】:

【参考方案1】:

如果您只想将用户在登录界面中提供的密码与存储在 LDAP/Active Directory 中的密码进行比较,您应该使用 ldap_bind 命令与用户 dn 和密码进行比较。当密码和用户名/DN 匹配时返回 true,否则返回 false。

要获取 DN,您通常需要与对 ldap 具有读取权限的已知用户绑定,通过用户名搜索用户,然后使用返回的用户 DN 和密码再次绑定。 https://gist.github.com/heiglandreas/5689592

有一个要点说明了这一点

如果您还想设置您想与用户绑定的用户密码,并且通常只允许用户(和管理员帐户)读取(和写入)用户密码。因此,您还希望像以前一样继续,然后添加一个调用来更新用户密码属性。有关解决方案和更深入的知识,请查看 f.e. http://www.letu.edu/people/markroedel/netcccu/activedirectorypasswordchanges.htm

更新密码以外的其他用户数据也将使用 ldap_modify 或 ldap_mod_replace 完成

【讨论】:

【参考方案2】:

使用 ldap_modify 更新 ldap 条目。这很简单:

$entry['mail'] = 'example@domain.com';
$entry['cn'] = 'test';
ldap_modify($connection, $dn, $entry);

userPassword 是一个操作属性。

服务器内部使用操作属性。通常,它是可读的,但用户不能修改。

为了检索 操作 属性,您必须明确要求它或使用特殊属性 + 请求所有属性(就像您使用 * 请求所有 用户属性)。

您还可以通过以下方式请求所有(用户和操作)属性:

ldap_search($connection, $base_dn, $filter, ['*', '+']);

现在,您想将提交的用户密码与存储在 AD 中的密码哈希字符串进行比较。这意味着您需要根据 AD 使用的哈希方案(例如:SSHA, SHA, SMD5, MD5, CRYPT, ...)手动对提交的字符串进行加密/哈希/加盐,以便比较可行。

这里是一个如何根据明文密码手动生成 MD5 哈希的示例:

$hash = 'md5' . base64_encode(pack('H*', md5($clear_txt_passwd)));

=> 这并不简单,即使输入字符串正确,也不能保证匹配,因为您可能会遇到 ldap 实现和/或系统/操作系统之间的互操作性问题(哈希/盐函数可能从一到另一个,尤其是使用依赖于系统的crypt 库)。

如果您想直接针对 AD 测试用户身份验证,只需使用 ldap_bind :

$bind = ldap_bind($connection, $dn, $passwd); // returns TRUE on success, FALSE on failure.
echo "$dn\n" . ($bind ? 'LDAP bind OK' : 'LDAP bind failed');

但是,例如,如果要根据现有的 openLdap 服务器和 AD 检查用户凭据,则需要不断同步/复制用户条目,而最好保留一个单一的身份验证后端。在这种情况下,您必须使用Pass-Through Authentication 在第一个后端使用专用的SASL 方案(本例中为openLDAP):使用此配置,Cyrus SASL 用作密码处理程序和委托使用 SASL 对任何后端服务器进行密码验证支持检查密码(在您的情况下为 AD,但它可能是 Kerberos 或 IMAP 服务器)。

【讨论】:

我想我起初误读了这篇文章.. 以前没有提到任何地方使用 openLDAP !因此,如果你们中的一些人对直通身份验证建议感到困惑,我很抱歉,我编辑了我的答案以澄清。 感谢您的提示!我尝试使用算法 'md5' 加密密码。 base64_encode(pack('H*', md5($clear_txt_passwd)));与 SSHA、SHA、SMD5、MD5、CRYPT。但这是行不通的。我有示例加密密码:jZiW2VK2W09xTe。它当然适用于一位用户。如果我使用 jZiW2VK2W09xTe 而不为一个用户加密它是工作。但是当我尝试为另一个用户(用户名:test_user,密码:qwertyPass)加密另一个密码时,它不起作用 - 身份验证失败。你能告诉我如何正确加密密码以在 AD 上使用 ldap 进行身份验证吗?

以上是关于如何在 php 中使用 LDAP 从 Active Directory 搜索和更新用户数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring 安全性从 Active Directory LDAP 填充 LDAP 权限?

通过 Active Directory 使用 LDAP 在 PHP 中进行身份验证

LDAP:如何从 Active Directory 中获取所有用户和组

C# - 使用 LDAP 检索 Active Directory 的组成员

PHP - 针对 Windows 2003 Active Directory 的 LDAP 身份验证(用户 ID 不同于名字和姓氏)

使用 LDAP 在 Active Directory 中查找用户 - 没有用户?