PHP Conference Japan 2024

ldap_modify

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

ldap_modifyldap_mod_replace() 的別名

說明

此函式是 ldap_mod_replace() 的別名。

參見

新增筆記

使用者貢獻筆記 16 則筆記

ace at suares dot nl
20 年前
關於 ldap_modify 的一些評論,尤其是來自 tengel at fluid dot com 的使用者評論

OpenLDAP 2.1.22
如果屬性在 schema 中標記為 MUST,則該屬性必須存在。它是否可以包含空值取決於該屬性的 SYNTAX。

DirectoryString 不得為空;OctetString 可以為空。據我所知,IA5String 不得為空。

如果屬性在 schema 中定義為 MAY,則該屬性可能存在或不存在。如果它存在,它可能為空或不為空,這取決於其 SYNTAX。

PHP 4.3.1

看來 ldap_modify() 將接受要修改的屬性陣列。

對於多值屬性,傳遞一個空陣列,將會刪除該屬性,無論其先前的值如何,也無論該屬性在修改之前是否存在。

如果將多值屬性定義為 MAY,這將會起作用。如果將屬性定義為 MUST,OpenLDAP 將會產生錯誤:'LDAP error 65: Object class violation'

如果屬性的 SYNTAX 定義為不得為空,則嘗試使用空值新增或修改該屬性將會產生錯誤:'LDAP error 21: Invalid syntax'。
此外,在記錄檔中,如果設定了足夠的除錯層級,則會出現字串

value #0 invalid per syntax

。將會出現。

嘗試將空陣列傳遞給 ldap_add() 以取得任何屬性(多值或單值)將會導致錯誤「LDAP error 2: Protocol error」,無論該屬性是定義為 MUST 還是 MAY。

請注意,這與傳遞沒有值的元素陣列不同。在後一種情況下,這是否允許取決於該屬性的 SYNTAX。

如果屬性是單值的,則傳遞一個包含一個元素的陣列,將會變更該屬性的值。在 php.net 上的使用者評論中建議,如果要修改單值屬性,則必須傳遞字串,而不是包含一個元素的陣列。我的經驗是,包含一個元素的陣列也能正常運作。

_Ace

網站:http://www.suares.nl * http://www.qwikzite.nl
chris at uffbasse dot de
20 年前
為了精確指出刪除問題

在較新版本的 OpenLdap 中,這將會失敗

$values["mail"] = "";
ldap_modify($conn_id, $dn, $values);


$values["mail"][0] = "";
ldap_modify($conn_id, $dn, $values);

但是這會起作用

$values["mail"] = array();
ldap_modify($conn_id, $dn, $values);


$values["mail"][0] = array();
ldap_modify($conn_id, $dn, $values);
docwoelle at ipwatch dot de
18 年前
如果想要在 Windows 的 Active Directory 中停用帳戶,
您可以嘗試這樣做(它在 Win2k 環境中對我有效)

(在 "$ldapBase" 中應將 foo.bar 取代為正確的
網域,例如,如果您的網域是 phpfreackx.com,則為 "DC=phpfreackx,DC=com")

domctrl = 網域控制站
domadlogin = 網域管理員登入
domadpw = 網域管理員密碼
username = 使用者帳戶的登入名稱(例如 "john.doe")
enable = 1(如果要啟用它,如果應停用則為 0)

<?php
function userchange($username,$enable=1,$domadlogin,$domadpw,$domctrl)
{
$ldapServer = $domctrl;
$ldapBase = 'DC=foo,DC=bar';
$ds = ldap_connect($ldapServer);
if (!
$ds) {die('無法連線到 LDAP 伺服器');}
$ldapBind = ldap_bind($ds,$domadlogin,$domadpw);
if (!
$ldapBind) {die('無法繫結到 LDAP 伺服器');}
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
$sr = ldap_search($ds, $ldapBase, "(samaccountname=$username)");
$ent= ldap_get_entries($ds,$sr);
$dn=$ent[0]["dn"];
// 停用
$ac = $ent[0]["useraccountcontrol"][0];
$disable=($ac | 2); // 設定所有位元加上位元 1 (=dec2)
$enable =($ac & ~2); // 設定所有位元減去位元 1 (=dec2)
$userdata=array();
if (
$enable==1) $new=$enable; else $new=$disable; //啟用或停用?
$userdata["useraccountcontrol"][0]=$new;
ldap_modify($ds, $dn, $userdata); //變更狀態
$sr = ldap_search($ds, $ldapBase, "(samaccountname=$username)");
$ent= ldap_get_entries($ds,$sr);
$ac = $ent[0]["useraccountcontrol"][0];
if ((
$ac & 2)==2) $status=0; else $status=1;
ldap_close($ds);
return
$status; //傳回目前狀態 (1=已啟用,0=已停用)
}

// 使用此程式碼停用帳戶:
// userchange('john.doe@foo.bar',0,'admin@foo.bar', 'secret','domctrl.foo.bar');
// ..但使用此程式碼啟用帳戶:
// userchange('john.doe@foo.bar',1,'admin@foo.bar', 'secret','domctrl.foo.bar');
?>
goetz at rvs dot uni-hannover dot de
21 年前
請記住,您不能使用 ldap_modify 修改 'objectclass' 屬性!

如果您使用搜尋結果作為修改的基礎,請務必 'unset()' 所有數字索引、'count' 索引以及 'objectclass' 索引!
kevin at guarana dot org
17 年前
如果您在 ldap_modify 中看到令人困惑的 "Type or value exists" 錯誤,原因可能是您嘗試為多值屬性添加兩個相同的值。例如,像這樣:

<?php
$le
= array("mail" => array("foo@bar.com", "foo@bar.com"));
$result = ldap_modify($ldap_link, $dn, $le);
?>
jmw1982 at gmail dot com
19 年前
如果您使用 ldap_modify() 為屬性寫入多個值,該函式會嘗試寫入值陣列中的所有條目,即使這些條目為空白。以用於屬性刪除的方式,將空白條目設定為空白陣列,例如:

$attributes[$attr_name][3] = array ();

會導致字串 "Array" 被寫入目錄中的該值。我發現唯一能做到我想做的事情的方法是只寫入表單上提交的屬性值,就是要檢查每個屬性是否有多個值,然後 unset() 空白值,例如:

foreach ($attributes as $key => $cur_val) {
if ($cur_val== '') {
$attributes[$key] = array ();
}
if (is_array ($cur_val)) {
foreach ($cur_val as $mv_key => $mv_cur_val) {

if ($mv_cur_val == '') {
unset ($attributes[$key][$mv_key]);
}
else {
$attributes[$key][$mv_key] = $mv_cur_val;
}
}
}
}
fechner at ponton dot de
21 年前
如果您在使用 md5 雜湊時嘗試更改 userPassword 屬性,請嘗試以下幾行:

$new["userPassword"] = '{md5}' . base64_encode(pack('H*', md5($newpass_in_plaintext)));
ldap_modify($ds, $dn, $new);
davidsmith at byuNOSPAM dot edu
21 年前
$entry 參數可以是屬性的值陣列。請注意,您的陣列索引必須是數值連續的。例如,當使用此 $entry 陣列時,ldap_modify 將會失敗,而且沒有太多說明:

$entry = array( 0 => 'foo', 2 => 'bar' );

而這個則可以正常運作:

$entry = array( 0 => 'foo', 1 => 'bar' );

希望這對某人有所幫助。
jpdalbec at ysu dot edu
21 年前
Nick T. 上面的評論已經過時了。
PHP LDAP 介面目前支援使用 ldap_rename() 函式直接修改 DN。
php_notes at grumz dot net
17 年前
根據 goetz at rvs dot uni-hannover dot de 的評論,ldap_modify 無法更改 objectclass 的說法並不完全正確。

事實上,不可能添加在綱要描述中設定為 STRUCTURAL 的 objectclass。但是您可以添加設定為 AUXILIARY 的 objectclass。請參閱下面的 OpenLDAP FAQ 以了解原因:

http://www.openldap.org/faq/data/cache/1341.html

例如,如果您有一個類型為 "device" 的 LDAP 條目,這是一個結構 objectclass,名為 "cn=myNetCard,ou=Networks,dc=example,dc=com",您可以執行以下操作:

<?php

$entry
["objectclass"][0] = "device";
$entry["objectclass"][1] = "ieee802Device"; // add an auxiliary objectclass
$entry["macAddress"][0] = "aa:bb:cc:dd:ee:ff";

ldap_modify ($cnx, "cn=myNetCard,ou=Networks,dc=example,dc=com", $entry);
?>

但是這樣做行不通:

<?php

$entry
["objectclass"][0] = "device";
$entry["objectclass"][1] = "ipNetwork"; // add a structural objectclass
$entry["ipNetworkNumber"][0] = "1.2.3.4";

ldap_modify ($cnx, "cn=myNetCard,ou=Networks,dc=example,dc=com", $entry);
?>

您會收到以下錯誤:"Cannot modify object class"
NOSPAMjjhuff at mspin dot net
22 年前
刪除條目:

$data["description"] = array();
ldap_modify($conn, $dn,$data);
tengel at fluid dot com
23 年前
OpenLDAP 從 1.x 到 2.x 的行為發生了變化;在 1.x 中,當您將陣列傳遞給 ldap_modify 時,如果值為空,則會刪除該屬性。在 2.x 中,您會收到 "Invalid Syntax" 錯誤,並且修改失敗。

這需要 ldap_mod_del 函式;不幸的是,該操作需要刪除的屬性指定其 *舊* 值 -- 您可以想像,如果您從 CGI 表單獲取輸入,則要刪除的屬性的值現在已遺失(即,使用者清空了表單中的文字方塊並按一下「提交」)。

所以,您陷入了一個兩難的困境 -- 您想要刪除「空」的表單值,但是您需要它們的舊值才能刪除它們。有很多方法可以處理此問題,但我選擇了這種方法:

<?php
// 第一個是要新增的,第二個是要移除的
$entry=array();
$delval=array();

// 想像一下,$o 和 $title 是
// 具有文字方塊的表單欄位,用於輸入資料
if($o!="") { $entry["o"]="$o"; } else { $delval[]="o"; }
if(
$title!="") { $entry["title"]="$title"; } else { $delval[]="title"; }

// 先嘗試使用 $entry 進行標準修改
// $ldap、$dn、$BASEDN 都在之前設定好
if (@ldap_modify($ldap, $dn, $entry)) {
// 然後執行繁瑣的工作
$filter = sprintf("(&(uid=%s)(sn=%s))",$uid,$sn);
$sres = ldap_search($ldap, $BASEDN, $filter, $delval);
$delent = ldap_first_entry($ldap, $sres);
$delarr = ldap_get_attributes($ldap, $delent);
$findel=array();
for(
$i=0; $i<$delarr["count"]; $i++) {
$attr = $delarr[$i];
$totl = $delarr[$attr]["count"];
for(
$z=0; $z<$totl; $z++) {
if (
$totl = 1) {
$findel[$attr]=$delarr[$attr][$z];
} else {
$findel[$attr][$z]=$delarr[$attr][$z];
}
}
}
if(@
ldap_mod_del($ldap, $dn, $findel)) {
print(
"<H3>修改條目!</H3>\n");
print(
"<BR>\n");
} else {
$error=ldap_error($ldap);
print(
"<H3>屬性刪除失敗!</H3>\n");
print(
"<BR>\n($error)\n");
}
} else {
$error=ldap_error($ldap);
print(
"<H3>修改失敗!</H3>\n");
print(
"<BR>\n($error)\n");
}
?>
nickt at powys dot gov dot uk
25 年前
使用 ldap_modify() 修改現有的 LDAP 資訊

link_identifier 必須來自於呼叫連線到伺服器的結果,並且具有更新條目的權限,通常需要經過驗證的繫結 - 也就是說,您需要在 ldap_bind() 呼叫中提供合適的 dn 和密碼。

dn 必須是 LDAP 伺服器上存在的單個特定 dn。LDAP 中沒有全域變更多個 dn 條目的萬用字元機制。

entry 陣列必須採用兩種不同的形式之一,具體取決於是否要為特定屬性在目錄中儲存一個條目,還是要為該屬性儲存多個條目。

如果要為屬性儲存單個條目 - 例如只有一個電子郵件地址 - 那麼您可以使用一般形式:

<?php $newinfo[ <attribute_name> ]="whatever" ; ?>

例如...

<?php $newinfo["mail"]="john@myorg.com" ; ?>

如果要為一個屬性儲存多個條目(例如一個人的多個電子郵件地址),則您可以使用以下一般形式

<?php
$newinfo
[ <attribute_name> ][0] = "whatever" ;
$newinfo[ <attribute_name> ][1] = "another" ;
?>

例如...

<?php
$newinfo
["mail"][0]="johnw@myorg.com" ;
$newinfo["mail"][1]="jwaterson@somewhere.org" ;
?>

關於 ldap_modify() 的進一步說明

修改呼叫會保留所有其他屬性的條目不變。因此,如果您只想更新「mail」屬性的條目,則只需要

<?php
$newinfo
[mail]="nick@county.gov.uk";
ldap_modify($valid_ldaplink, $valid_dn, $newinfo);
?>

但是,如果您在執行上述程式碼時,LDAP 資料庫中存在多個 mail 屬性的條目,那麼所有現有的 mail 條目都會被刪除,並被單個 "mail" 條目取代。

如果您有理由預期特定屬性有多個值(例如多個電子郵件條目),則應確保先從 ldap 伺服器讀取所有條目,然後儲存修改後的陣列。

PHP LDAP 介面目前不支援直接修改 dn。如果需要變更 dn,唯一的方法是讀取 dn 的所有條目,並將這些條目儲存到新的、修改過的 dn 中,然後刪除原始 dn 的完整條目。
匿名
9 年前
當我嘗試將使用者新增至 Active Directory 中的使用者群組時,遇到了一個相當惱人的問題。

當您嘗試修改 "memberOf" 屬性 (透過 ldap_mod_add/ldap_mod_replace) 時,Active Directory 往往不太高興,並且會在某處輸出類似以下的警告/錯誤

Warning: ldap_mod_add(): Modify: Server is unwilling to perform in ...

如果您想將使用者新增至使用者群組,您需要將使用者新增為群組的成員,而不是新增至群組的 memberOf 屬性

<?php
function ldap_addToGroup($username, $group) {
$dn = "CN=$group,OU=Accounts,DC=DC1,DC=DC2"; // 您想要新增到的群組的 distinguished name/DN
$info["member"] = "CN=$username,OU=Accounts,DC=DC1,DC=DC2"; // 您想要新增的使用者的 DN
return ldap_modify($ldapconn, $dn, $info);
}
?>

希望這對某人有幫助。
spam at bilgoraj dot info
11 年前
如果您無法使用 ldap_modify 將屬性 objectclass 新增至現有物件,請使用 ldap_mod_add - 它有效。
匿名
9 年前
當我嘗試將使用者新增至 Active Directory 中的使用者群組時,遇到了一個相當惱人的問題。

當您嘗試修改 "memberOf" 屬性 (透過 ldap_mod_add/ldap_mod_replace) 時,Active Directory 往往不太高興,並且會在某處輸出類似以下的警告/錯誤

Warning: ldap_mod_add(): Modify: Server is unwilling to perform in ...

如果您想將使用者新增至使用者群組,您需要將使用者新增為群組的成員,而不是新增至群組的 memberOf 屬性

<?php
function ldap_addToGroup($username, $group) {
$dn = "CN=$group,OU=Accounts,DC=DC1,DC=DC2"; // 您想要新增到的群組的 distinguished name/DN
$info["member"] = "CN=$username,OU=Accounts,DC=DC1,DC=DC2"; // 您想要新增的使用者的 DN
return ldap_modify($ldapconn, $dn, $info);
}
?>

希望這對某人有幫助。
To Top