PHP Conference Japan 2024

ldap_add

(PHP 4, PHP 5, PHP 7, PHP 8)

ldap_add向LDAP目录添加条目

描述

ldap_add(
    LDAP\Connection $ldap,
    string $dn,
    array $entry,
    ?array $controls = null
): bool

在LDAP目录中添加条目。

参数

ldap

一个 LDAP\Connection 实例,由 ldap_connect() 返回。

dn

LDAP实体的区分名称。

entry

一个数组,指定条目的信息。条目中的值按各个属性索引。对于属性的多个值,使用从0开始的整数索引。

<?php
$entry
["attribute1"] = "value";
$entry["attribute2"][0] = "value1";
$entry["attribute2"][1] = "value2";
?>

controls

要与请求一起发送的 LDAP 控制 数组。

返回值

成功返回 true,失败返回 false

变更日志

版本 描述
8.1.0 ldap 参数现在期望一个 LDAP\Connection 实例;之前,期望一个有效的 ldap link 资源
8.0.0 controls 现在可以为空;之前,它默认为 []
7.3.0 添加了对 controls 的支持

示例

示例 #1 使用经过身份验证的绑定完成示例

<?php
$ds
= ldap_connect("localhost"); // 假设LDAP服务器在此主机上

if ($ds) {
// 使用适当的dn绑定以提供更新访问权限
$r = ldap_bind($ds, "cn=root, o=My Company, c=US", "secret");

// 准备数据
$info["cn"] = "John Jones";
$info["sn"] = "Jones";
$info["objectclass"] = "person";

// 将数据添加到目录
$r = ldap_add($ds, "cn=John Jones, o=My Company, c=US", $info);

ldap_close($ds);
} else {
echo
"无法连接到LDAP服务器";
}
?>

备注

注意: 此函数是二进制安全的。

参见

添加备注

用户贡献的备注 23条备注

stian
17年前
此解决方案对我们有效。
在表单中,CN和pwdtxt是从严格规则中随机生成的。
此脚本每天在AD中创建50-60个用户!并且从未出现任何故障!

<?php
## 从表单获取数据
$CN = $_POST['CN'];
$givenName = $_POST['givenName'];
$SN = $_POST['SN'];
$mail = $_POST['mail'];
$Phone = $_POST['Phone'];
$pwdtxt = $_POST['pwdtxt'];

$AD_server = "localhost:390"; // 本地 Stunnel --> http://www.stunnel.org/
$AD_Auth_User = "[email protected]"; // 管理员用户
$AD_Auth_PWD = "duppiduppdupp"; // 密码

$dn = 'CN='.$CN.',OU=Brukere,DC=student,DC=somwhere,DC=com';

## 创建 Unicode 密码
$newPassword = "\"" . $pwdtxt . "\"";
$len = strlen($newPassword);
$newPassw = "";

for(
$i=0;$i<$len;$i++) {
$newPassw .= "{$newPassword{$i}}\000";
}

## 连接到 AD
$ds = ldap_connect($AD_server);
if (
$ds) {
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // 重要
$r = ldap_bind($ds, $AD_Auth_User, $AD_Auth_PWD); // 绑定

$ldaprecord['cn'] = $CN;
$ldaprecord['givenName'] = $givenName;
$ldaprecord['sn'] = $SN;
$ldaprecord['objectclass'][0] = "top";
$ldaprecord['objectclass'][1] = "person";
$ldaprecord['objectclass'][1] = "organizationalPerson";
$ldaprecord['objectclass'][2] = "user";
$ldaprecord['mail'] = $mail;
$ldaprecord['telephoneNumber'] = $Phone;
$ldaprecord["unicodepwd"] = $newPassw;
$ldaprecord["sAMAccountName"] = $CN;
$ldaprecord["UserAccountControl"] = "512";
// 这可以防止用户被禁用。 -->
http://support.microsoft.com/default.aspx?scid=kb;en-us;305144

$r = ldap_add($ds, $dn, $ldaprecord);

} else {
echo
"无法连接到 LDAP 服务器 $AD_server.";
}

?>

这是一个在 AD 中创建用户的代码示例。
我们将其用于内部网页,以创建
可以访问无线网络的临时用户。
我们有一个 .pl 脚本,用于在 24 小时后删除用户。
damien at groovey dot com
17年前
以下是如何在 OpenLDAP 中添加具有 MD5 哈希密码的用户。我使用此技术将 Drupal 帐户迁移到 OpenLDAP,以实现单点登录解决方案。

诀窍是告诉 OpenLDAP 哈希类型(例如 {MD5})位于密码之前,并且还要对二进制哈希结果进行 Base64 编码。你不能只对 PHP 的 md5() 或 sha() 哈希函数返回的结果进行 Base64 编码,因为它们返回的是十六进制文本字符串。首先,你必须使用 pack("H*", $hash_result) 将其转换为二进制字符串,然后才能对其进行 Base64 编码。

以下是连接并添加具有哈希密码的用户的完整代码。你不必使用 {MD5},如果你的哈希方式不同,可以选择其他哈希方式。这些哈希密码的输出将如下所示:{md5}bdwD04RS9xMDGVi1n/H36Q==

最后是一些注意事项:如果你使用盐值对密码进行哈希,则此技术无效(但 Drupal 没有使用)。此技术肯定不适用于活动目录,在活动目录中,密码只能通过 SSL 连接设置,并且哈希方式可能有所不同。

---- 省略 ----

$ds = ldap_connect($serverAddress);
if ($ds) {
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // 否则 PHP 默认使用 ldap v2,你会得到语法错误!
$r = ldap_bind($ds, $managerDN, $managerPassword);
$ldaprecord['cn'] = $newuser_username;
$ldaprecord['givenName'] = $newuser_firstname;
$ldaprecord['sn'] = $newuser_surname;
// 将用户放入 objectClass inetOrgPerson 对象类中,以便可以设置邮件和电话号码属性
$ldaprecord['objectclass'][0] = "person";
$ldaprecord['objectclass'][1] = "organizationalPerson";
$ldaprecord['objectclass'][2] = "inetOrgPerson";
$ldaprecord['mail'] = $newuser_email_address;
$ldaprecord['telephoneNumber'] = $newuser_phone_number;
// 现在是棘手的部分,对二进制哈希结果进行 Base64 编码
$ldaprecord['userPassword'] = '{MD5}' . base64_encode(pack('H*',$newuser_md5hashed_password));
// 如果你有纯文本密码,你可以使用
// $ldaprecord['userPassword'] = '{MD5}' . base64_encode(pack('H*',md5($newuser_plaintext_password)));
$r = ldap_add($ds, $base_user_dn, $ldaprecord);
} else { die "无法连接到 LDAP 服务器 $serverAddress。"; }
Axel D. (FRANCE)
21 年前
如果你不知道如何在 AD Win2K 中添加用户,请尝试使用此脚本。
要了解有关属性的更多信息,请在 Win2K 的支持工具中打开 adsiedit 控制台。

$adduserAD["cn"][0] =
$adduserAD["instancetype"][0] =
$adduserAD["samaccountname"][0] =
$adduserAD["objectclass"][0] = "top";
$adduserAD["objectclass"][1] = "person";
$adduserAD["objectclass"][2] = "organizationalPerson";
$adduserAD["objectclass"][3] = "user";
$adduserAD["displayname"][0] =
$adduserAD["name"][0] =
$adduserAD["givenname"][0] =
$adduserAD["sn"][0] =
$adduserAD["company"][0] =
$adduserAD["department"][0] =
$adduserAD["title"][0] =
$adduserAD["description"][0] =
$adduserAD["mail"][0] =
$adduserAD["initials"][0] =
$adduserAD["samaccountname"][0] =
$adduserAD["userprincipalname"][0] =
$adduserAD["profilepath"][0] =
$adduserAD["manager"][0] = ***使用 DistinguishedName***

if (!($ldap = ldap_connect("localhost"))) {
die ("无法连接到 LDAP 服务器");
}
if (!($res = @ldap_bind($ldap, "[email protected]", $password))) {
die ("无法绑定到 LDAP 帐户");
}
if (!(ldap_add($ldap, "CN=New User,OU=OU Users,DC=pc,DC=com", $adduserAD))){
echo "创建帐户时出现问题";
echo "请联系你的管理员!";
exit;
}
ldap_unbind($ldap);
theiderich AT laweekly dot com
19 年前
在添加/编辑用户的属性时,请记住“memberof”属性是一个特殊情况。“memberOf”属性不是用户模式的可访问属性。要将某人添加到组中,你必须将用户添加到组中,而不是将组添加到用户中。你可以通过访问组属性“member”来实现此目的。

<?php

$group_name
= "CN=MyGroup,OU=Groups,DC=example,DC=com";
$group_info['member'] = $dn; // 用户的 DN 添加到组的“member”数组中
ldap_mod_add($connect,$group_name,$group_info);

?>
ondrej dot duchon at t-systems dot cz
20 年前
jharnett at artschool dot com
对于 AD 中的活动用户,你必须将“useraccountcontrol”更改为 512,512 = 已启用,514 = 已禁用
phil at networkalliance dot com
16 年前
我创建了一个简单的函数,可以调用它来在活动目录中创建全局通讯组。

<?php
function ldap_createGroup($object_name, $dn, $members, $ldap_conn)
{
$addgroup_ad['cn']="$object_name";
$addgroup_ad['objectClass'][0] = "top";
$addgroup_ad['objectClass'][1] ="group";
$addgroup_ad['groupType']="2";
$addgroup_ad['member']=$members;
$addgroup_ad["sAMAccountName"] =$object_name;

ldap_add($ldap_conn,$dn,$addgroup_ad);

if(
ldap_error($ldap_conn) == "Success")
return
true;
else
return
false;
}
?>

可以使用以下代码调用此函数

<?php
$ldap_conn
= ldap_bind();
$object_name="Test Group";
$dn="CN=".$object_name.",OU=PathToAddGroupTo,OU=All Users,DC=YOURDOMAIN,DC=COM";
$members[] ="CN=User1,OU=PathToAddGroupTo,OU=All Users,DC=YOURDOMAIN,DC=COM";
$members[] ="CN=User2,OU=PathToAddGroupTo,OU=All Users,DC=YOURDOMAIN,DC=COM";

ldap_createGroup($object_name, $dn, $members, $ldap_conn);
?>

我创建的另一个函数是 ldap_bind(),它可以用于绑定到 LDAP 服务器

<?php
function ldap_bind()
{
$ldap_addr = '192.168.1.1'; // 将此更改为 LDAP 服务器的 IP 地址
$ldap_conn = ldap_connect($ldap_addr) or die("Couldn't connect!");
ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
$ldap_rdn = "domain_name\\user_account";
$ldap_pass = "user_password";

// 将用户对域控制器进行身份验证
$flag_ldap = ldap_bind($ldap_conn,$ldap_rdn,$ldap_pass);
return
$ldap_conn;
}
?>
sergioshev
16 年前
我添加使用布尔语法 (1.3.6.1.4.1.1466.115.121.1.7) 的属性时遇到问题

$['boolean_attr']=true; // 这给了我一个警告,ldap_add(): Add: Invalid syntax

通过将值设置为以下内容解决了这个问题

$['boolean_attr']='TRUE';

希望这有帮助。
spam2004 at turniton dot dk
20 年前
在 Windows AD 中添加组…
$object_name="testgroup2";
$members[]="CN=THU,ou=Users,dc=addomain,dc=domain,dc=dk";
$members[]="CN=testgroup2,ou=Groups,dc=addomain,dc=domain,dc=dk";
$addgroup_ad['cn']="$object_name";
$addgroup_ad['objectClass'][0] = "top";
$addgroup_ad['objectClass'][1] ="group";
$addgroup_ad['descripton']=$object_description;
$addgroup_ad['member']=$members;
$addgroup_ad["sAMAccountName"] =$object_name;

// 注意参数 2 (dn) 可能会有所不同
$dn="cn=".$object_name.",ou=Groups,dc=addomain,dc=domain,dc=dk";
ldap_add($ldapc,$dn,$addgroup_ad);
John Van Atta
21 年前
针对 jharnett 关于默认情况下由 ldap_add 禁用的帐户的问题,我们找到了一个解决方案。

属性 userAccountControl 包含一个值,其中包括帐户是否已禁用或启用。我们的默认值为 546;当我们将它更改为 544 时,帐户被启用。更改 userAccountControl 中的值 2 似乎可以启用或禁用帐户。

以下代码对我们创建具有启用帐户的新用户有效

$adduserAD["userAccountControl"] = "544";

我们只是将此元素添加到上面示例的数组中。
hp at syntomax dot com
20 年前
另一件有趣的事情:ldap_add() 不喜欢具有空成员的数组:因此
array (
[cn] = "name"
[key] = ""
[anotherkey] = "value"
)
将产生语法错误!

使用一段简单的代码解决此问题

foreach ($originalobject as $key => $value){
if ($value != ""){
$object[$key] = $value;
}
}

其中 $originalobject 是未经检查的数组,$object 是没有空成员的数组。
akohlsmith at mixdown dot org
25 年前
只有当属性有多个值时,ldap_add() 才会遵循 $entry["attribute"][x]="value"。如果只有一个属性值,则*必须*将其输入为 $entry["attribute"]="value",否则 ldap_add() 会将属性的值设置为“Array”,而不是您放入 $entry["attribute"][0] 中的值。

这里是我编写的一个小程序来自动执行此操作。解析输入时,只需使用 multi_add()
<?php
function multi_add($attribute, $value)
{
global
$entry; // 您要添加的 LDAP 条目

if(isset($entry[$attribute]))
if(
is_array($entry[$attribute]))
$entry[$attribute][count($entry[$attribute])] = $value;
else
{
$tmp = $entry[$attribute];
unset(
$entry[$attribute]);
$entry[$attribute][0] = $tmp;
$entry[$attribute][1] = $value;
}
else
$entry[$attribute] = $value;
}
?>
multi_add() 检查属性是否已存在值。如果没有,则将其添加为 $entry[$attribute]=$value。如果属性已存在值,则将其转换为数组并正确添加多个值。

使用方法
<?php
switch($form_data_name)
{
case
'phone': multi_add("telephoneNumber", $form_data_value); break;
case
'fax': multi_add("facsimileTelephoneNumber", $form_data_value); break;
case
'email': multi_add("mail", $form_data_value); break;
...
}
?>
在我的系统设计中,表单具有下拉菜单,名称为 ctype1、ctype2、ctype3 等,值是“fax、mail、phone…”。实际的联系数据(电话号码、传真、电子邮件等)是 contact1、contact2、contact3 等。用户下拉选择联系类型(电话、电子邮件),然后输入数据(号码、地址等)。

我使用变量变量来填充条目并跳过空格。这使得表单输入系统非常简洁。如果您对此感兴趣,请给我发送电子邮件,因为我认为我超过了此处允许的注释大小。 :-)
Baumkuchen.TH
6 年前
在 Active Directory 中创建组

<?php
$ds
= ldap_connect("IP-服务器/localhost");
$base_dn = "CN=组名,OU=组织单元,DC=域名,DC=com";//组的distinguishedName

if ($ds) {
// 使用合适的dn绑定以获得更新权限
ldap_bind($ds, "CN=管理员,OU=组织单元,DC=域名,DC=com", "some-password");

// 向组中添加成员
$member_array = array();
$member_array[0] = "CN=管理员,OU=组织单元,DC=域名,DC=com";
$member_array[1] = "CN=用户,OU=组织单元,DC=域名,DC=com";

$entry["cn"] = "GroupTest";
$entry["samaccountname"] = "GroupTest";
$entry["objectClass"] = "Group";
$entry["description"] = "组测试!!";
$entry["member"] = $member_array;
$entry["groupType"] = "2";//groupType="2" 为分发组 / groupType="1" 为安全组

ldap_add($ds,$base_dn,$entry);

ldap_close($ds);
} else {
echo
"无法连接到LDAP服务器";
}
?>
[email protected]
11年前
当我尝试添加posixAccount和shadowAccount作为objectclass时,我一直收到“对象类冲突”错误。事实证明,这些对象类有很多我未添加的必需字段。您可能需要导出一个有效的用户(如果您有phpLDAPadmin)并查看其确切的字段,然后尝试在脚本中精确复制。第一次将所有内容都设为数组也没有坏处,以后可以修复这些字段。
[email protected]
19 年前
我使用了spam2004在turniton.dk上的示例,并对其进行了改进。也许我的设置略有不同,无论如何,以下是我在Microsoft Windows Server 2003中添加组的方法。

<?php
// 使用ldap_connect连接
// 使用ldap_bind绑定
// 将LDAP_OPT_PROTOCOL_VERSION设置为3
$member_array = array();
$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";

$addgroup_ad["cn"] = "testgroup";
$addgroup_ad["samaccountname"] = "testgroup";
$addgroup_ad["objectClass"] = "Group";
$addgroup_ad["description"] = "是的,只是一个测试。";
$addgroup_ad["member"] = $member_array;
$base_dn = "cn=testgroup,cn=Users,DC=yourdomain,DC=com";
ldap_add($ldap_conn,$base_dn,$addgroup_ad);
// 就这样。
?>

保重,祝你好运!
Chad R. Smith
amcnabb
20 年前
注意类型。PHP会在字符串和数字之间自动切换,但LDAP不会,除非您指定类型,否则PHP会发送对PHP最方便的任何内容,而不是LDAP。

如果您无意中将数字作为字符串发送,则会收到错误:“ldap_add(): Add: [filename]第LINENUM行语法无效。”

观察此示例,它创建一个数组发送给LDAP以创建POSIX组。请注意,$new_groupid 从技术上讲是字符串,必须使用(int)进行类型转换。

$new_ldap_group['cn'] = $groupname;
$new_ldap_group['objectclass'][0] = 'posixgroup';
$new_ldap_group['objectclass'][1] = 'top';
$new_ldap_group['gidnumber'] = (int) $new_groupid;
[email protected]
20 年前
如果您需要使用国家字符(iso 8859-2、8等),使用ldap_set_option是个好方法。
找到错误很不容易 ;-)))。我希望这对某些人有所帮助。

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
[email protected]
22年前
由于某种奇怪的原因,使用ldap_add()添加新帐户后,帐户被设置为“inactive”。
据我所见,没有可修改的属性可以“重新启用”该用户。我想默认情况下,如果未设置特定标志,则使用默认值。任何有解决方案的人,请发布,我快没头发了。
[email protected]
22年前
如果您需要添加二进制编码的属性(例如:userCertificate),则需要在字段名称末尾添加“;binary”规范。

例如

$info["userCertificate;binary"] = $myBinaryCert;
$ldap_add ...

Del
[email protected]
23年前
请注意,您不能使用base64编码,而必须改为对特殊字符使用utf-8编码。
Willie
17年前
回复
请注意,您不能使用base64编码,而必须改为对特殊字符使用utf-8编码。
--

我发现,如果我有特殊字符(或换行符),ldap_add和ldap_modify会自动为您进行base64编码。例如

<?php
// 假设已完成绑定等。
$entry['postalAddress'] = "123 East 456 West\nSuite A103";
ldap_modify($ds, $dn, $entry);
?>

该函数或服务器会自动将换行符转换为base64(其他特殊字符也是如此)。

您可以使用命令行ldapsearch进行验证
ldapsearch -b "dc=example,dc=com" -x "(cn=Example Person)" postalAddress

您会看到结果如下所示
dn: cn=Example Person,dc=example,dc=com
postalAddress:: MTIzIEVhc3QgNDU2IFdlc3QKU3VpdGUgQTEwMw==

看到postal address后的双冒号了吗?在这种情况下,LDAP就是以此表示它是base64编码的。
[email protected]
19 年前
当遇到可怕的无效语法时,打开ldap中的调试会有所帮助。查看/var/log/ldap,会得到如下信息

5月2日 13:51:21 tux slapd[12985]: conn=4934 op=1 RESULT tag=105 err=21 text=phpgwtz: 值#0根据语法无效
5月2日 13:52:02 tux slapd[12697]: 条目(uid=1, ou=adressen, dc=...)没有objectClass
Andrew ([email protected])
21 年前
关于帐户启用的问题,您可以使用Microsoft支持网站上的表格来帮助处理这些属性。

您说得对,“2”是帐户禁用标志,但还有其他标志,允许您检测/设置密码强制过期等。

希望此URL对您有用

http://support.microsoft.com/default.aspx?scid=kb;en-us;305144

干杯。
Igor2i
11年前
我决定专门为俄语用户添加此内容。
我的服务器是Gentoo,支持UTF-8编码的西里尔字母。
通过表单输入西里尔字母时,会显示语法错误。
解决方法
1) 需要将代码转换为不带BOM的UTF-8
2) 在代码开头插入一行
<?php
header
('Content-Type: text/html; charset=utf-8');
?>
To Top