2024 PHP Conference Japan (日本 PHP 研討會)
新增筆記

使用者貢獻的筆記 32 則筆記

nick dot veitch at futurenet dot co dot
21 年前
列出這裡可用的運算子可能很有用

= - 完全符合值
=*xxx - 符合以 xxx 結尾的值
=xxx* - 符合以 xxx 開頭的值
=*xxx* - 符合包含 xxx 的值
=* - 符合所有值(如果設定 - 不會返回 NULL)

>=xxx - 符合從 xxx 到目錄結尾的所有內容
<=xxx - 符合目錄中到 xxx 為止的所有內容

~=xxx - 符合相似項目(並非所有系統都支援)

用於構建複雜搜尋的布林運算子

&(term1)(term2) - 符合 term1 且符合 term2
| (term1)(term2) - 符合 term1 或符合 term2
!(term1) - 不符合 term1
&(|(term1)(term2))(!(&(term1)(term2)) - 符合 term1 與 term2 的互斥或 (XOR)

某些較複雜的結構似乎以不同程度的效率運作 - 有時最好用搜尋過濾一些結果,並在 PHP 中進行進一步過濾。
jayleno at yahoo dot com
11 年前
<?php
set_time_limit
(30);
error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
ini_set('display_errors',1);

// config
$ldapserver = 'svr.domain.com';
$ldapuser = 'administrator';
$ldappass = 'PASSWORD_HERE';
$ldaptree = "OU=SBSUsers,OU=Users,OU=MyBusiness,DC=myDomain,DC=local";

// connect
$ldapconn = ldap_connect($ldapserver) or die("Could not connect to LDAP server.");

if(
$ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldapuser, $ldappass) or die ("Error trying to bind: ".ldap_error($ldapconn));
// verify binding
if ($ldapbind) {
echo
"LDAP bind successful...<br /><br />";


$result = ldap_search($ldapconn,$ldaptree, "(cn=*)") or die ("Error in search query: ".ldap_error($ldapconn));
$data = ldap_get_entries($ldapconn, $result);

// SHOW ALL DATA
echo '<h1>Dump all data</h1><pre>';
print_r($data);
echo
'</pre>';


// iterate over array and print data for each entry
echo '<h1>Show me the users</h1>';
for (
$i=0; $i<$data["count"]; $i++) {
//echo "dn is: ". $data[$i]["dn"] ."<br />";
echo "User: ". $data[$i]["cn"][0] ."<br />";
if(isset(
$data[$i]["mail"][0])) {
echo
"Email: ". $data[$i]["mail"][0] ."<br /><br />";
} else {
echo
"Email: None<br /><br />";
}
}
// print number of entries found
echo "Number of entries found: " . ldap_count_entries($ldapconn, $result);
} else {
echo
"LDAP bind failed...";
}

}

// all done? clean up
ldap_close($ldapconn);
?>
aa529 at nospamchebucto dot ns dot ca
25 年前
從使用者輸入產生過濾條件時,請注意特殊字元。

*, (, ), \ 和 NUL 應以反斜線跳脫。請參閱 RFC 2254 的第 4 節(我在這裡找到它
http://www.cis.ohio-state.edu/htbin/rfc/rfc2254.html)
Arnold
13 年前
我一直在開發一個指令碼,需要取得特定 MS AD 群組的所有成員使用者。由於 PHP 錯誤 #42060 ( http://bugs.php.net/bug.php?id=42060 ),我無法取得該群組的所有成員使用者。
在 Google 上搜尋了一天後,我找到了一篇文章和一個修補程式,但它需要我下載 php 5.1.6 或 5.2.10 的原始碼,執行修補程式,然後重新編譯程式碼以修復問題。
問題是
1) 我不是 Linux 專家,所以我對這樣做不是很舒服....
2) 我在使用 PHP 的其他程式碼的正式機器上執行指令碼,不知道這會對該程式碼產生什麼影響。
3) 我無法再更新 PHP,因為在新版本中,此修補程式可能無法再運作。

但昨天我看到了曙光,並編寫了一些程式碼來解決這個問題,也許其他有同樣問題的人可以使用它。

<?PHP
$startFilter
= "(&(memberOf=" .$ADGroup. "))";
$startResults = ldap_search($ldapconnect, $userBase, $startFilter, $attr);
$countResult = ldap_count_entries($ldapconnect,$startResults);

IF(
$countResult == 1000 OR $countResult == 1500)
{
// loop trough the number 97-122 (ASCII number for the characters a-z)
For($a=97;$a<=122;$a++)
{
// translate the number to a character
$character = chr($a);
// the new search filter withs returns all users with a last name starting with $character
$filter = "(&(sn=$character*)(memberOf=$ADGroup))";
$results = ldap_search($ldapconnect, $userBase, $filter, $attr);
$countResult2 = ldap_count_entries($ldapconnect,$results);

// See if the search for all users starting with a specific character still hits the search limit
// if so than do a new search to find all the users where the last name starts with "aa" and
// than with "ab", "ac" etc. etc
// In the best case we can now find 675.324 users per group when the search limit is 1000
// ((26 * 999 for the fist character) * 26 for the second character)
// and 1.013.324 when the search limit is 1500
If($countResult2 == 1000 or $countResult2 == 1500)
{
For(
$b=97;$b<=122;$b++)
{
$character2 = chr($b);
$filter2 = "(&(sn=$character$character2*)(memberOf=$ADGroup))";
$results2 = ldap_search($ldapconnect, $userBase, $filter2, $attr);
$count2 = ldap_count_entries($ldapconnect,$results2);
$entries2 = ldap_get_entries($ldapconnect,$results2);

// do your thing
}
}
Else
{
$entries = ldap_get_entries($ldapconnect,$results);
// do your thing
}
}
}
else
{
$entries = ldap_get_entries($ldapconnect,$startResults);
// do your thing
}
?>
steven_bauman at outlook dot com
4 年前
可以新增一個使用新的 $serverctrls 參數的範例嗎?我不知道如何使用它。
cruzfern at chuchuwa dot com dot ar
19 年前
內部屬性(例如 createTimestamp、modifyTimestamp 等)並非預設提供(在未設定選用參數 attributes 的情況下)。您必須明確指定它。

<?
$r=ldap_search($ds,$base,$filter,array("createTimestamp"));
?>
chrisbloom7 at gmail dot com
17 年前
以下是一些關於正確建構篩選器的資源。

http://msdn2.microsoft.com/En-US/library/aa746475.aspx

http://technet.microsoft.com/en-us/library/aa996205.aspx

在找到這些資源之前,我一直苦惱了好幾個小時,想著如何執行類似「所有以 'a' 開頭的使用者,但排除來自 OU 'foo' 的使用者」這樣的搜尋。
sembiance at cosmicrealms dot com
21 年前
搜尋二進位資料(例如 Active Directory 的 objectGUID)時,您需要使用反斜線跳脫每個十六進位字元。

以下 ldapsearch 命令列執行範例:
ldapsearch -b "dc=blahblah,dc=com" "(objectGUID=\AE\C3\23\35\F7)"

在 PHP 中,您需要對反斜線本身進行跳脫。
ldap_search($ds,"dc=blahblah,dc=com", "(objectGUID=\\AE\\C3\\23\\35\\F7)");
francis dot tyers at hp dot com
21 年前
即使在 ldapsearch 輸出中是大小寫混合的,似乎所有欄位都必須使用小寫。

範例

gidNumber: 1010
homeDirectory: /home/dnt

必須寫成

echo "gid: " . $info[$i]["gidnumber"][0] . "<br>";
echo "home directory: ". $info[$i]["homedirectory"][0] ."<br>";

而不是 ( $info[$i]["homeDirectory"][0] ) 等等。
cdaveb at csua dot berkeley dot edu
23 年前
僅供參考,對於在 Exchange 伺服器上執行 LDAP 搜尋的人來說,Exchange 似乎傾向於不允許非初始搜尋(例如,只有 x* 可以運作,* 或 *x 則不行)。我一直很困惑,試圖找出為什麼執行 * 搜尋時總是出現錯誤。

更多資訊請參考
http://www.microsoft.com/Exchange/en/55/help/documents/server/XOG16007.HTM
Jean-Loup
12 年前
平行搜尋範例

<?php
$basedn
=array('dmdName=users,dc=foo,dc=fr','dmdName=users,dc=bar,dc=com'); // 兩個基底 DN
$filter='(&(objectClass=inetOrgPerson)(uid=*))'; // 單一過濾條件
$attributes=array('dn','uid','sn');

$cnx = ldap_connect('localhost',389); // 單一連線
ldap_set_option($cnx, LDAP_OPT_PROTOCOL_VERSION, 3);

ldap_bind($cnx,'uid=root,dc=foo,dc=fr','password'); // 在兩個 BDB 上進行驗證
ldap_bind($cnx,'uid=root,dc=bar,dc=com','password');

$search = ldap_search(array($cnx,$cnx),$basedn,$filter,$attributes); // 搜尋

// 結果
for($i=0;$i<count($search);$i++){
print_r(ldap_get_entries($cnx,$search[$i]));
print
"\n";
}
?>
nicolas at atanis dot net
21 年前
這裡有一小段程式碼,可以執行完整的子樹搜尋(我知道上面有一段程式碼似乎可以做到,但它無法正常運作)
這是我的版本

Voilà ce que j'ai fait aujourd'hui ... (法文:這就是我今天做的...)

$ldap_host = "192.168.0.50";
$ldap_port = "389";
$base_dn = "dc=fr";
$filter = "(cn=*)";
$ldap_user ="cn=admin,dc=fr";
$ldap_pass = "hellodelu";
$connect = ldap_connect( $ldap_host, $ldap_port);
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);

$bind = ldap_bind($connect, $ldap_user, $ldap_pass);
$read = ldap_search($connect, $base_dn, $filter);

$info = ldap_get_entries($connect, $read);
echo $info["count"]." 筆資料回傳<BR><BR>";
for($ligne = 0; $ligne<$info["count"]; $ligne++)
{
for($colonne = 0; $colonne<$info[$ligne]["count"]; $colonne++)
{
$data = $info[$ligne][$colonne];
echo $data.":".$info[$ligne][$data][0]."<BR>";
}
echo "<BR>";
}
ldap_close($connect);

--------
nicolas
sema at technion dot ac dot il
20 年前
要在 Windows 2003 Server Active Directory 上執行搜尋,您必須將 LDAP_OPT_REFERRALS 選項設定為 0

ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

如果沒有這個設定,當您嘗試搜尋整個 AD 結構描述(使用網域的根目錄作為 $base_dn)時,您會收到「操作錯誤」。

這與 Windows 2000 Server 不同,在 Windows 2000 Server 中,此選項是可選的,僅用於提高效能。
john_taylor_1973 at yahoo dot com
22 年前
盡可能使用 ldap_list(),它速度更快。ldap_search 的搜尋範圍是 LDAP_SCOPE_SUBTREE,而 ldap_list 的搜尋範圍僅為 LDAP_SCOPE_ONELEVEL。即使查詢只返回 130 個物件,這在 Novell eDirectory 8.6.1 上也造成了很大的差異。使用屬性列表(兩個函式的第四個參數)也能加快查詢速度。
jpdalbec at ysu dot edu
22 年前
我發現搜尋篩選器中的空格需要被跳脫字元 ("\20") 轉義,至少在使用 Red Hat PHP 4.1.2 套件時是如此。否則不會返回任何結果。
chester at the dot underground dot com dot au
21 年前
如果您正在搜尋 Active Directory 並且遇到延遲或逾時,可能是因為 LDAP 伺服器向您提供了 LDAP 參考。以下程式碼將停用此功能。

<?
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
?>
mike at remi-designs dot net
8 年前
我遇到了我正在搜尋的屬性具有「exactMatch」(完全相符)比對規則的問題。

範例
電子郵件地址以大小寫混合的方式儲存:John.Doe@example.com

當使用者輸入:john.doe@example.com 時,LDAP 搜尋將不會擷取任何值。

解決方案:不要透過以下方式比較使用者輸入和屬性值:

<?php
if($data[$i]['mail'][0] == $username) {
// 這樣不會有任何結果
}
?>

改用 strcasecmp

<?php
if(strcasecmp($data[$i]['mail'][0], $username) == 0) {
// 可以運作
}
me at gavinadams dot org
21 年前
關於 AD LDAP 搜尋的 minor clarification(次要說明)。先前的範例中有一個小錯字,並且沒有顯示每個屬性的多個值。以下是用於列舉所有項目、屬性和值的 for 迴圈

$bind = ldap_bind($connect) // 假設匿名連線或新增使用者/密碼
或 exit(">>無法繫結到 $ldap_host<<");
$read = ldap_search($connect, $base_dn, $filter)
或 exit(">>無法搜尋 LDAP 伺服器<<");
$info = ldap_get_entries($connect, $read);
echo $info["count"]." 個項目已返回<br>";
// $i = 項目
// $ii = 項目的屬性
// $iii = 每個屬性的值
for ($i = 0; $i<$info["count"]; $i++) {
for ($ii=0; $ii<$info[$i]["count"]; $ii++){
$data = $info[$i][$ii];
for ($iii=0; $iii<$info[$i][$data]["count"]; $iii++) {
echo $data.":&nbsp;&nbsp;".$info[$i][$data][$iii]."<br>";
}
}
echo "<p>"; // 分隔項目
peter dot mlich at volny dot cz
4 年前
我的 LDAP 類別中的程式碼範例。

public function query($_filter, $_att, $_ref=2, $count_bool=true)
{
$fn = 'query';
$config = $this->config;
$conn = $this->conn;
if (!$conn)
{return $this->errorConnection($fn);}
ldap_set_option($conn, LDAP_OPT_DEREF, $_ref);
$result = ldap_search($conn, $config['baseDn'], $_filter, $_att); // 或 die(ldap_error($conn))
if ($result===false)
{
$this->error("搜尋錯誤,不存在!");
return false;
}
$count = ldap_count_entries($conn, $result);
if ($count_bool && $count!=1)
{
$this->error("搜尋錯誤,並非唯一!計數=".$count);
ldap_free_result($result);
return false;
}
$data = ldap_get_entries($conn, $result);
ldap_free_result($result);
return $data;
}

// ---

$filter = "(&(objectclass=person)(cn=" . $user_name . "))";
$att = array(
'uid',
'workforceID',
'employeeID',
'givenName',
'sn',
'mail'
);
$data = $this->query($filter, $att, 2, true);
anze dot pratnemer at fe dot uni-lj dot si
5 年前
在開發一個插件時,我必須使用 ldap_search() 命令在 LDAP 伺服器上搜尋使用者,但它找不到使用者,然而在 Unix shell (Ubuntu) 中的 ldapsearch 命令卻可以。

問題出在我的程式碼中,ldap_connect() 附近幾行。我輸入 ldap://server.hostname 作為伺服器地址,結果這就是罪魁禍首。

一旦我只使用 server.hostname,不帶協議 (ldap://),就可以找到並正確顯示使用者。
Allie
17 年前
我剛在 ldap_bind 上發布了訊息,但我想在這邊也提一下也無妨,因為這是我試圖找出問題所在的第一站。我的錯誤指向 ldap_search,但指定 ldap_connect 連接埠才是解決方法。

當您想要搜尋整個 MS AD 目錄時,您必須在綁定中指定連接埠 3268。這也適用於 Apache auth_ldap。

$ldapserver = ldap_connect($server,3268);
php @ fccfurn dot com
21 年前
要在 Active Directory 中從頂層 DN 進行子樹搜尋,請確保您執行了 ldap_set_option()。

<?php
$ldap_host
= "pdc.php.net";
$base_dn = "DC=php,DC=net";
$filter = "(cn=Joe User)";
$ldap_user = "CN=Joe User,OU=Sales,DC=php,DC=net";
$ldap_pass = "pass";
$connect = ldap_connect( $ldap_host, $ldap_port)
or exit(
">>無法連線到 LDAP 伺服器<<");
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass)
or exit(
">>無法綁定到 $ldap_host<<");
$read = ldap_search($connect, $base_dn, $filter)
or exit(
">>無法搜尋 LDAP 伺服器<<");
$info = ldap_get_entries($connect, $read);
echo
$info["count"]." 筆項目回傳<p>";
$ii=0;
for (
$i=0; $ii<$info[$i]["count"]; $ii++){
$data = $info[$i][$ii];
echo
$data.":&nbsp;&nbsp;".$info[$i][$data][0]."<br>";
}
ldap_close($connect);
?>
匿名
23 年前
我使用以下程式碼從 ILS (Netmeeting) 伺服器擷取所有項目:<p> $sr=ldap_search($ds, "objectclass=rtperson","(&(cn=%)(objectclass=rtperson))");
<p>祝您使用愉快!
<p>Kees
ben _at_ onshop_co_uk
15 年前
示範搜尋多個 DN(多個辨別名稱)的範例

<?php
$ds
=ldap_connect($ldapserver);

$dn[]='OU=ABC,DC=xyz,DC=ac,DC=uk';
$dn[]='OU=DEF,DC=xyz,DC=ac,DC=uk';

$id[] = $ds;
$id[] = $ds;

$filter = 'samaccountname='.$_POST['username'];

$result = ldap_search($id,$dn,$filter);

$search = false;

foreach (
$result as $value) {
if(
ldap_count_entries($ds,$value)>0){
$search = $value;
break;
}
}

if(
$search){
$info = ldap_get_entries($ds, $search);
}else{
$info = 'No results found';
}
?>
ben _at_ onshop.co.uk
14 年前
承接我於 2009 年 11 月 11 日 06:56 關於使用 LDAP 查詢 AD 時,DN 問題的記錄(而非使用全域目錄),進一步調查顯示,儘管結果已在封包中,但我卻收到錯誤訊息

「搜尋:無法連線到 LDAP 伺服器」也就是錯誤 81。

使用更詳細的分析

ldap_get_option($ds,LDAP_OPT_ERROR_STRING,$error);

echo $error

顯示

參考:ldap://DomainDnsZones.defg.de.bc.ac.uk/ DC=DomainDnsZonesDC=defg,DC=de,DC=abc,DC=ac,DC=uk

透過反覆試驗,當使用以下程式碼時,錯誤消失並返回結果

ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
Kamil Kukura <kamk at nexen dot cz>
21 年前
當我嘗試在命名上下文為 "" 的 OpenLDAP 伺服器上使用空的 base DN 進行搜尋時,我得到「找不到此物件」的結果。在日誌檔案中,有一個 dn 的查詢:dc=example,dc=com(!)
作為一種解決方法,似乎只要以空格 (' ') 作為 base DN 即可 - ldap_search($ds, ' ', '(...filter...)', ...
neumeyed at city dot bloomington dot in dot us
21 年前
先前的評論指出:「我也注意到 departmentNumber、employeeNumber(可能還有 inetorgperson.schema 中的其他項目)不會從搜尋中返回。」

這是錯誤的。這些屬性會被回傳,但您必須使用小寫名稱來引用它們。也就是說,不要這樣做:

$entries[0]["departmentNumber"][0]

而應該這樣做:

$entries[0]["departmentnumber"][0]

這對我來說不像「正確的」行為,但我對 LDAP 的了解不夠深入,無法確定。
openldap at mail dot doris dot cc
19 年前
PHP 4.3.10

我嘗試在沒有 basedn 的情況下執行 ldapsearch。首先,我嘗試了如上建議的 ' ',但它給了我無效的 dn 語法錯誤。

例如:
$sr=ldap_search($ds, ' ', $filter);
警告:ldap_search():搜尋:無效的 DN 語法,位於...

然後我將其更改為
$sr=ldap_search($ds, "", $filter);

這給了我以下錯誤
警告:ldap_search():搜尋:找不到此物件,位於...

接著我修改了我的 ldap.conf 檔案,並將 BASE 欄位註釋掉
#BASE dc=example, dc=com

然後它就成功了!

所以看起來,如果您提供空白的 basedn,它就會使用您在 ldap.conf 中的預設 basedn。
info at acpower dot biz
13 年前
我是新手,所以我希望這能幫助其他一些遇到難題的新手...

這段程式碼返回了「找不到此物件」的錯誤

<?php

$search
= ldap_search ($ldapcon, "cn=admin,dc=acpower,dc=biz", "(filters)");

?>

我去掉了 cn,神奇的是!它可以運作了

<?php

$search
= ldap_search ($ldapcon, "dc=acpower,dc=biz", "(filters)");

?>
emrecio at netscape dot net
22 年前
implode(", ",$uentry[0]["rfc822mailalias"]);

無法如預期般運作,因為其中包含 "count" 元素…您「必須」使用 'for' 迴圈來循環瀏覽結果(並捨棄 "count" 元素)。
fmouse at fmp dot com
19 年前
用於 LDAP 過濾器資訊的 Netscape Directory SDK (developer.netscape.com) 參考似乎不再接受連線。定義 LDAP 過濾器字串表示標準的 RFC 2254 副本可以在 http://www.ietf.org/rfc/rfc2254.txt 找到
nick
13 年前
來自 ActiveDirectory 的結果可能會根據 objectSid 排序。
我們可以透過修改過濾器來取得每個頁面大小的所有使用者。

<?php
// ... 連線到 ldap
$lastsid='';
while (
1) {
$filter = '(objectClass=user)';
if (
strlen($lastsid)) {
list(
$v)=array_values(unpack('V',substr($lastsid,24))); // 使用者的 ID
$s = substr($lastsid,0,24).pack('V',1+$v); // 下一個 sid
$s = preg_replace('/../','\\\\$0',bin2hex($s)); // 為了過濾條件而跳脫字元
$filter = '(&'.$filter.'(objectSid>='.$s.'))'; // 下一筆資料的過濾條件
}
$res = ldap_search($ldap,$basedn,$filter,array('objectSid','cn'));
if (!
ldap_count_entries($ldap,$res)) {
break;
}
for (
$ent=ldap_first_entry($ldap,$res); $ent; $ent=ldap_next_entry($ldap,$ent)) {
list(
$lastsid) = ldap_get_values_len($ldap,$ent,'objectSid');
}
}
?>
To Top