PHP Conference Japan 2024
添加注释

用户贡献的注释 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 的异或

一些更复杂的结构似乎以不同程度的效率工作 - 有时候,最好先用搜索过滤一些结果,然后在 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);

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

// 连接
$ldapconn = ldap_connect($ldapserver) or die("无法连接到 LDAP 服务器。");

if(
$ldapconn) {
// 绑定到 ldap 服务器
$ldapbind = ldap_bind($ldapconn, $ldapuser, $ldappass) or die ("绑定错误: ".ldap_error($ldapconn));
// 验证绑定
if ($ldapbind) {
echo
"LDAP 绑定成功...<br /><br />";


$result = ldap_search($ldapconn,$ldaptree, "(cn=*)") or die ("搜索查询错误: ".ldap_error($ldapconn));
$data = ldap_get_entries($ldapconn, $result);

// 显示所有数据
echo '<h1>转储所有数据</h1><pre>';
print_r($data);
echo
'</pre>';


// 遍历数组并打印每个条目的数据
echo '<h1>显示用户</h1>';
for (
$i=0; $i<$data["count"]; $i++) {
//echo "dn is: ". $data[$i]["dn"] ."<br />";
echo "用户: ". $data[$i]["cn"][0] ."<br />";
if(isset(
$data[$i]["mail"][0])) {
echo
"邮箱: ". $data[$i]["mail"][0] ."<br /><br />";
} else {
echo
"邮箱: 无<br /><br />";
}
}
// 打印找到的条目数
echo "找到的条目数: " . ldap_count_entries($ldapconn, $result);
} else {
echo
"LDAP 绑定失败...";
}

}

// 全部完成?清理
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 bug #42060(http://bugs.php.net/bug.php?id=42060),我无法获取该组的所有用户。
在谷歌搜索了一天后,我找到了一篇文章和一个补丁,但它要求我下载 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)
{
// 循环遍历97到122之间的数字(字符a到z的ASCII码)
For($a=97;$a<=122;$a++)
{
// 将数字转换为字符
$character = chr($a);
// 新的搜索过滤器,返回所有姓氏以$character开头的用户
$filter = "(&(sn=$character*)(memberOf=$ADGroup))";
$results = ldap_search($ldapconnect, $userBase, $filter, $attr);
$countResult2 = ldap_count_entries($ldapconnect,$results);

// 查看以特定字符开头的所有用户的搜索是否仍然达到搜索限制
// 如果是,则进行新的搜索,查找姓氏以“aa”开头的所有用户,
// 然后是“ab”,“ac”等等
// 在最佳情况下,当搜索限制为1000时,我们现在可以找到每个组675,324个用户
// ((第一个字符的26 * 999) * 第二个字符的26)
// 搜索限制为1500时,则为1,013,324个用户
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);

// 执行你的操作
}
}
Else
{
$entries = ldap_get_entries($ldapconnect,$results);
// 执行你的操作
}
}
}
else
{
$entries = ldap_get_entries($ldapconnect,$startResults);
// 执行你的操作
}
?>
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对象GUID)时,需要使用反斜杠转义每个十六进制字符。

以下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'); // 两个basedn
$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 年前
这是一个执行完整子树搜索的小脚本(我知道上面有一个脚本似乎可以做到这一点,但它不能正常工作)
这是我的版本

这是我今天做的...

$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范围。这在Novell eDirectory 8.6.1上产生了很大的差异,即使对于仅返回130个对象的查询也是如此。使用属性列表,即第四个函数参数(两个函数中的任何一个),也可以使查询更快。
jpdalbec at ysu dot edu
22年前
我发现至少在使用Red Hat PHP 4.1.2软件包时,需要在搜索过滤器中转义空格("\20")。否则不会返回任何结果。

chester at the dot underground dot com dot au
21 年前
如果您正在搜索活动目录并且遇到延迟或超时,可能是LDAP服务器正在提供LDAP引用。以下代码将禁用此功能。

<?
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
?>
mike at remi-designs dot net
8年前
我遇到了一个问题,即我正在搜索的属性具有“exactMatch”的匹配规则。

示例
电子邮件地址以混合大小写存储:[email protected]

当用户输入以下内容时,LDAP搜索将不会检索任何值:[email protected]

解决方案:不要使用

<?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搜索的小澄清。前一个示例中有一个小错误,并且没有显示每个属性的多个值。以下是枚举所有条目、属性和值的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=".$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(多个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 = '未找到结果';
}
?>
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服务器上使用空基本DN进行搜索时,我得到了“不存在此对象”的结果。在日志文件中,查询的dn为:dc=example,dc=com(!)
作为解决方法,似乎使用空格(' ')作为基本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(): Search: Invalid DN syntax in ...

然后我将其更改为
$sr=ldap_search($ds, "", $filter);

这给了我以下错误
警告:ldap_search(): Search: No such object in ...

然后我修改了我的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)不再接受连接。RFC 2254的副本定义了LDAP过滤器的字符串表示的标准,可以在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