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 連線 資源
8.0.0 現在 controls 可為 null;先前則預設為 []
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 個附註

5
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 = "administrator@student.somwhere.com"; // 管理員使用者
$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
"無法連線到位於 $AD_server 的 LDAP 伺服器。";
}

?>

這是一個在 AD 中建立使用者的程式碼範例。
我們在內部網頁上使用它來建立
可以存取無線網路的臨時使用者。
我們有一個 .pl 腳本會在 24 小時後刪除使用者。
5
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==

最後是一些注意事項:如果使用 Salt 值雜湊密碼,此技術將無法運作 (但 Drupal 沒有)。此技術也肯定無法與 Active Directory 搭配使用,Active Directory 中的密碼絕對只能透過 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,以便我們設定 mail 和 phone number 屬性
$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 "無法連線到位於 $serverAddress 的 LDAP 伺服器。"; }
6
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, "user@pc.com", $password))) {
die ("無法綁定到 LDAP 帳戶");
}
if (!(ldap_add($ldap, "CN=新使用者,OU=OU 使用者,DC=pc,DC=com", $adduserAD))){
echo "建立帳戶時發生問題
echo "請聯絡您的管理員!";
exit;
}
ldap_unbind($ldap);
5
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);

?>
2
ondrej dot duchon at t-systems dot cz
20 年前
jharnett at artschool dot com
對於 AD 中的使用中使用者,您必須將 "useraccountcontrol" 變更為 512,512 = 已啟用,514 = 已停用
4
phil at networkalliance dot com
16 年前
我建立了一個簡單的函數,可用於在 Active Directory 中建立全域通訊群組

<?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("無法連線!");
ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
$ldap_rdn = "網域名稱\\使用者帳戶";
$ldap_pass = "使用者密碼";

// 驗證使用者對網域控制器的身份
$flag_ldap = ldap_bind($ldap_conn,$ldap_rdn,$ldap_pass);
return
$ldap_conn;
}
?>
3
sergioshev
16 年前
我曾經在新增具有布林語法的屬性時遇到問題 (1.3.6.1.4.1.1466.115.121.1.7)

$['boolean_attr']=true; //給我一個警告,ldap_add(): 新增:語法無效

透過將值設定為此解決了這個問題

$['boolean_attr']='TRUE';

希望這對您有所幫助。
1
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);
1
John Van Atta
21 年前
針對 jharnett 關於 ldap_add 預設停用帳戶的問題,我們已找到解決方案。

userAccountControl 屬性包含一個值,其中包含帳戶是否停用或啟用。我們的預設值是 546;當我們將其變更為 544 時,帳戶就會啟用。將 userAccountControl 中的任何值變更 2 似乎可以啟用或停用帳戶。

以下程式碼對我們來說可以建立一個具有啟用帳戶的新使用者

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

我們只是將此元素新增到上述範例的陣列中。
1
hp at syntomax dot com
20 年前
另一個有趣的事情:ldap_add() 不喜歡具有空成員的陣列:所以
陣列 (
[cn] = "名稱"
[key] = ""
[anotherkey] = "值"
)
會產生語法錯誤!

使用簡單的一段程式碼解決此問題

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

其中 $originalobject 是未檢查的陣列,$object 是沒有空成員的陣列。
1
akohlsmith at mixdown dot org
25 年前
ldap_add() 只會在 *屬性有多個值時*才會接受 $entry["attribute"][x]="value"。如果屬性只有一個值,則*必須*輸入為 $entry["attribute"]="value",否則 ldap_add() 會將屬性的值設定為「陣列」,而不是您放入 $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
'電話': multi_add("telephoneNumber", $form_data_value); break;
case
'傳真': multi_add("facsimileTelephoneNumber", $form_data_value); break;
case
'電子郵件': multi_add("mail", $form_data_value); break;
...
}
?>
在我設計的系統中,表單的下拉式選單有 ctype1、ctype2、ctype3 等名稱,值為「傳真、郵件、電話...」。實際的聯絡資料(電話號碼、傳真、電子郵件等)為 contact1、contact2、contact3 等。使用者會下拉選擇聯絡類型(電話、電子郵件),然後輸入資料(號碼、地址等)。

我使用可變變數來填寫項目並略過空白。這建立了一個非常乾淨的表單輸入系統。如果您對此感興趣,請寄電子郵件給我,因為我認為我已經超出這裡允許的筆記大小。 :-)
0
Baumkuchen.TH
6 年前
在 Active Directory 中建立群組

<?php
$ds
= ldap_connect("IP-server/localhost");
$base_dn = "CN=群組名稱,OU=組織單位,DC=網域名稱,DC=com";//群組的 distinguishedName

if ($ds) {
// 使用適當的 dn 綁定以提供更新權限
ldap_bind($ds, "CN=管理員,OU=組織單位,DC=網域名稱,DC=com", "一些密碼");

//在群組中新增成員
$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 伺服器";
}
?>
0
paul90brown at gmail dot com
11 年前
當我嘗試新增 posixAccount 和 shadowAccount 作為 objectclass 時,一直出現「Object Class Violation」。結果發現這些 object class 有許多我沒有新增的必填欄位。您可能需要匯出一個正常運作的使用者(如果您有 phpLDAPadmin),並確切查看他們有哪些欄位,然後嘗試在腳本中完全複製它。如果第一次將所有內容都設為陣列也沒有壞處,您可以稍後修正這些欄位。
0
chad dot smith at 50marketing dot com
19 年前
我採用了 spam2004 at turniton dot 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
0
amcnabb
20 年前
請注意類型。PHP 會自動在字串和數字之間切換,但 LDAP 不會,而且除非您指定類型,否則 PHP 會傳送對 PHP 最方便的任何內容,而不是 LDAP。

如果您不小心將數字當作字串傳送,您會收到錯誤:「ldap_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;
0
ondrej dot duchon at t-systems dot cz
20 年前
如果您需要使用國家字元 (iso 8859-2,8 等),最好使用 ldap_set_option。
要找到錯誤在哪裡是很困難的工作 ;-)))。我希望這對某些人有幫助。

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
0
jharnett at artschool dot com
22 年前
由於某些奇怪的原因,當使用 ldap_add() 新增新帳戶時,該帳戶會被設定為「非活動」。
而且從我看到的,沒有可修改的屬性可以「重新啟用」該使用者。我想預設情況下,如果沒有設定特定的旗標,則會使用預設值。任何有解決此問題的人,請發文,我快要拔光我僅剩的頭髮了。
0
del at babel dot com dot au
22 年前
如果您需要新增二進位編碼的屬性(例如:userCertificate),那麼您需要在欄位名稱的末尾新增 ";binary" 規格。

例如

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

Del
0
titus dot stahl at experts4 dot com
23 年前
請注意,您不能使用 base64 編碼,您必須改用 utf-8 編碼來處理特殊字元。
-1
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 編碼的方式。
-1
micattack+phpnet at gmail dot com
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]:項目沒有 objectClass (uid=1, ou=adressen, dc=...
-1
Andrew (a.whyte at cqu.edu.au)
21 年前
關於帳戶啟用的問題,您可以使用 Microsoft 支援網站上的表格來協助處理這些屬性。

您說的沒錯,'2' 是帳戶已停用旗標,但還有其他旗標,可讓您偵測/設定密碼強制過期等。

希望這個 URL 對您有幫助

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

乾杯。
-4
Igor2i
11 年前
Решил добавить специально для русскоязычных пользователей.
У меня сервер на Gentoo с поддержкой кириллици в кодировке UTF-8.
И при вводе через форму кириллицы выдавал ошибку синтаксиса.
Решение проблемы
1) код требуется перекодировать в UTF-8 без BOM
2) и в начале кода вставить строку
<?php
header
('Content-Type: text/html; charset=utf-8');
?>
To Top