使用PHP连接LDAP服务器
本文将演示如何使用PHP连接一个LDAP服务器。具体的例子是连接到一个公共的LDAP服务器并且进行搜索。这个例子模拟的是Netscape Communicator 4.*,通过自己的地址本连接到LDAP资源。
LDAP介绍
可能不少人已经听说过LDAP,但是却不了解它具体是什么东东和如何工作。在这里我将不会很详细地介绍LDAP,只是对该协议做一个简介。
LDAP是一个用来发布目录信息到许多不同资源的协议。通常它都作为一个集中的地址本使用,不过根据组织者的需要,它可以做得更加强大。
LDAP最基本的形式是一个连接数据库的标准方式。该数据库为读查询作了优化。因此它可以很快地得到查询结果,不过在其它方面,例如更新,就慢得多。要特别注意的是,LDAP通常作为一个hierarchal数据库使用,而不是一个关系数据库。因此,它的结构用树来表示比用表格好。正因为这样,就不能用SQL语句了。
简单说来,LDAP是一个得到关于人或者资源的集中、静态数据的快速方式。
要求
PHPV.4(以前的版本也可以,不过没有经过测试),编译支持LADP,即使用编译时带--with-ldap公共的LDAP目录。在例子中提供了两个。
例子概览
1.设置公共LDAP服务器的信息
2.创建一个LDAP查询
3.连接到LDAP服务器
4.如果连接成功,处理查询
5.格式化输出
6.关闭连接
7.设计搜索界面的HTML表格
8.显示结果
设置公共LDAP服务器的信息
我们要做的第一件事情是定义所有欲搜索的LDAP服务器的信息
"LDAP_NAME" = 新的LDAP项目的名字
"LDAP_SERVER" = 新的LDAP项目的IP地址或者主机名
"LDAP_ROOT_DN" = 新的LDAP项目的根的辨识名
<?php
$LDAP_NAME[0] = "Netscape Net Center";
$LDAP_SERVER[0] = "memberdir.netscape.com";
$LDAP_ROOT_DN[0] = "ou=member_directory,o=netcenter.com";
$LDAP_NAME[1] = "Bigfoot";
$LDAP_SERVER[1] = "ldap.bigfoot.com";
$LDAP_ROOT_DN[1] = "";
//如果没有选择服务器的话将它设置为0
if(!$SERVER_ID)
$SERVER_ID=0;
?>
建立LDAP查询
前面已经提到,LDAP查询与SQL查询是不一样的。因此,语句要受到一定的限制,以下是一个基本的例子。
//Create Query $ldap_query = "cn=$common";
在我们的例子中,“cn”是我们要进行搜索的属性,而$common是由搜索的form中得到的字符串变量。LDAP的查询语句语句可使用通配符‘*’。例如‘$stanley’将可以找出‘dan stanley’。
连接到LDAP服务器
以下的函数连接到一个LDAP资源,并且将连接的识别号赋给一个变量,就好象连接到一个通常的数据库一样,例如MySQL。
<?php
//连接到LDAP
$connect_id = ldap_connect($LDAP_SERVER[$SERVER_ID]);
?>
在我们的例子中,“$connect_id”是连接的识别号,$LDAP_SERVER是可能的ldap服务器数组,而$SERVER_ID是由搜索表格得到的LDAP服务器变量。
如果连接成功,处理查询
如果连接成功的话,我们将得到一个有效的LDAP连接识别号,这样我们就可以处理查询。
<?php
if($connect_id)
{
//认证
$bind_id = ldap_bind($connect_id);
//执行搜索
$search_id = ldap_search($connect_id, $LDAP_ROOT_DN[$SERVER_ID], $ldap_query);
//将结果集合分配给一个数组
$result_array = ldap_get_entries($connect_id, $search_id);
}
else
{
//显示连接错误
echo "Could not connect to LDAP server: $LDAP_SERVER[$SERVER_ID]";
}
?>
一旦我们与LDAP服务器建立好连接,我们就必须进行认证。PHP在连接大多数的数据库时,都是通过发送用户名和密码来进行的。不过,在LDAP中,认证是未知的,直到进行一个bind操作。在我们的例子中,“$bind_id”是绑定连接的标识符。我们是通过匿名绑定到公共的LDAP服务器的。因此,在执行ldap_bind()时,只使用连接识别号就可以了,无需其它的参数。
在经过认证后(这里是匿名的),我们就可以使用ldap_search()函数来执行查询,产生的$search_id是我们搜索的连接识别符。
然后,我们使用ldap_get_entries()函数将结果集赋给$result_array变量。这样我们能够以逻辑的方式排列信息,以便显示。
格式化输出
在执行完LDAP搜索后,返回的数据是以查找的顺序排列的。不过我们在排序时没有SQL这样方便,使用ORDER BY语句就可以了。通常多数公共的LDAP目录都没有标准的大小规范。排序是基于字符的ASCII值,我们必须将字符全部格式化为小写,以便按字母的顺序输出。
要特别注意的是,返回的LDAP结果集是一个多维的数组。因此,我们脚本中的$result_array的结构如下:
$result_array[0]["cn"] [0] = "Dannie Stanley"
["dn"] [0] = "uid=dannie,dc=spinweb.net"
["givenname"][0] = "Dannie"
["sn"] [0] = "Stanley"
["mail"] [0] = "danSPAM@spinweb.net"
$result_array[1]["cn"] [0] = "Michael Reynolds"
["dn"] [0] = "uid=michael,dc=spinweb.net"
["givenname"][0] = "Michael"
["sn"] [0] = "Reynolds"
["mail"] [0] = "michaelSPAM@spinweb.net"
数据以这种格式存放的原因是每个属性都可能有超过一个值(象树的结构)。例如,如果我的名字是‘Dannie’,我还可以在LDAP中增加一些属性,例如:
$result_array[0]["cn"] [0] = "Dannie Stanley"
["dn"] [0] = "uid=dannie,dc=spinweb.net"
["givenname"][0] = "Dannie"
["givenname"][0] = "Dan"
["sn"] [0] = "Stanley"
["mail"] [0] = "danSPAM@spinweb.net"
在我们的搜索中,我们只关心每个属性的首个值,因此除了dn只有一个值外,其它我们只使用每个属性中序号为0的值。以下就是属性和它们含义的简单列表:
"cn" = Common Name
"dn" = Distinguished Name
"givenname" = First Name
"sn" = Last Name
"mail" = Email地址
<?php
//如果搜索成功,将结果排序
if($result_array)
{
for($i=0; $i
$format_array[$i][0] = strtolower($result_array[$i]["cn"][0]);
$format_array[$i][1] = $result_array[$i]["dn"];
$format_array[$i][2] = strtolower($result_array[$i]["givenname"][0]);
$format_array[$i][3] = strtolower($result_array[$i]["sn"][0]);
$format_array[$i][4] = strtolower($result_array[$i]["mail"][0]);
}
//排序数组
sort($format_array, "SORT_STRING");
for($i=0; $i
$cn = $format_array[$i][0];
$dn = $format_array[$i][1];
$fname = ucwords($format_array[$i][2]);
$lname = ucwords($format_array[$i][3]);
$email = $format_array[$i][4];
if($dn && $fname && $lname && $email)
{
$result_list .= "$fname $lname";
$result_list .= " $email>
\n";
}
elseif($dn && $cn && $email)
{
$result_list .= "<A href='/"ldap://$LDAP_SERVER[$SERVER_ID]/$dn/"'>$cn</A>";
$result_list .= " <A href='/"mailto:$email/"'>$email</A>
\n";
}
}
}
else
{
echo "Result set empty for query: $ldap_query";
}
?>
在我们的例子中,$format_array是我们建立的新数组,里面包括有查询的结果,并且被格式化用作输出。首先循环$result_array中的每个元素,并且将它分配给一个两维的数组用作排序。同时我们使用strtolower()函数将所有的值变为小写。
接着,我们使用PHP自带的一个称为sort()的函数进行排序。首个参数是要排序的数组,另一个是要执行的排序类型,该类型是由PHP的文档定义的。由于我们根据字符串排序,我们使用“SORT_STRING”。
第三,我们循环已经格式化好的数组,并且将它分配给一个名字为$result_list的输出字符,该字符包含了HTML描述。要特别注意的是,在超链接中,我使用的是ldap的URL格式。这个格式的例子类似:HREF="ldap://ldap.domain.net/uid=dannie,dc=domain.net"。
关闭连接
现在我们所有的数据已经包含在$result_list中了,我们可以安全地关闭LDAP的连接。
<?php
//关闭连接
ldap_close($connect_id);
?>
定制搜索界面的HTML表格
最后,我们要定制搜索用的HTML表格,它是用来给用户执行搜索的。
//定制表格
echo " <CENTER><FORM action='\"$PHP_SELF\"' method='\"GET\"'>";
echo "Search in:<SELECT name='\"SERVER_ID\"'>"; //循环以建立SELECT选项 for($i=0; $i<COUNT($LDAP_NAME); <br $i++)> echo "<OPTION selected value='\"$i\"'>".$LDAP_NAME[$i]."</OPTION>"; echo "</SELECT>
";
echo "Search for:<INPUT name='\"common\"' type='\"text\"'>";
echo "<INPUT name='\"lookup\"' type='\"submit\"' value='\"go\"'>
";
echo "(You can use * for wildcard searches, ex. * Stanley will find all Stanleys)
";
echo "</FORM></CENTER>";
?>
代码中的$PHP_SELF是一个全局的常量,代表的是脚本页面自身,其中的循环是用来通过我们的$LDAP_NAME变量创建SELECT选项。
显示结果
现在所有的工作已经完成了,我们将打印出结果集。如果没有符合的结果,将会显示"No Results"的信息。
//显示结果
if($result_list)
{
echo " <CENTER><TABLE border='\"1\"' cellPadding='\"10\"' cellSpacing='\"0\"'
BGCOLOR=\"#FFFFEA\" WIDTH=\"450\"> <TBODY><TR><TD>$result_list</TD></TR>
</TBODY></TABLE></CENTER>";
}
else
echo "No Results";
?>
源代码
以下是完整的源代码,只要将它剪切并粘贴到一个HTML文档,就可以尝试一下了。
<?php
$LDAP_NAME[0] = "Netscape Net Center";
$LDAP_SERVER[0] = "memberdir.netscape.com";
$LDAP_ROOT_DN[0] = "ou=member_directory,o=netcenter.com";
$LDAP_NAME[1] = "Bigfoot";
$LDAP_SERVER[1] = "ldap.bigfoot.com";
$LDAP_ROOT_DN[1] = "";
//如果没有选择服务器的话将它设置为0
if(!$SERVER_ID)
$SERVER_ID=0;
//建立查询
$ldap_query = "cn=$common";
//连接到LDAP
$connect_id = ldap_connect($LDAP_SERVER[$SERVER_ID]);
if($connect_id)
{
//认证
$bind_id = ldap_bind($connect_id);
//执行搜索
$search_id = ldap_search($connect_id, $LDAP_ROOT_DN[$SERVER_ID], $ldap_query);
//将结果集合分配给一个数组
$result_array = ldap_get_entries($connect_id, $search_id);
}
else
{
//显示连接错误
echo "Could not connect to LDAP server: $LDAP_SERVER[$SERVER_ID]";
}
//如果搜索成功,将结果排序
if($result_array)
{
for($i=0; $i
$format_array[$i][0] = strtolower($result_array[$i]["cn"][0]);
$format_array[$i][1] = $result_array[$i]["dn"];
$format_array[$i][2] = strtolower($result_array[$i]["givenname"][0]);
$format_array[$i][3] = strtolower($result_array[$i]["sn"][0]);
$format_array[$i][4] = strtolower($result_array[$i]["mail"][0]);
}
//排序数组
sort($format_array, "SORT_STRING");
for($i=0; $i
$cn = $format_array[$i][0];
$dn = $format_array[$i][1];
$fname = ucwords($format_array[$i][2]);
$lname = ucwords($format_array[$i][3]);
$email = $format_array[$i][4];
if($dn && $fname && $lname && $email)
{
$result_list .= "<A href='/"ldap://$LDAP_SERVER[$SERVER_ID]/$dn/"'>$fname $lname</A>";
$result_list .= " $email>
\n";
}
elseif($dn && $cn && $email)
{
$result_list .= "<A href='/"ldap://$LDAP_SERVER[$SERVER_ID]/$dn/"'>$cn</A>";
$result_list .= " \n";
}
}
}
else
{
echo "Result set empty for query: $ldap_query";
}
//关闭连接
ldap_close($connect_id);
//定制表格
echo " <CENTER><FORM action='\"$PHP_SELF\"' method='\"GET\"'>";
echo "Search in:<SELECT name='\"SERVER_ID\"'>"; //循环以建立SELECT选项 for($i=0; $i
";
echo "Search for:<INPUT name='\"common\"' type='\"text\"'>";
echo "<INPUT name='\"lookup\"' type='\"submit\"' value='\"go\"'>
";
echo "(You can use * for wildcard searches, ex. * Stanley will find all Stanleys)
";
echo "</FORM></CENTER>";
//显示结果
if($result_list)
{
echo " <CENTER><TABLE border='\"1\"' cellPadding='\"10\"' cellSpacing='\"0\"'
BGCOLOR=\"#FFFFEA\" WIDTH=\"450\"> <TBODY><TR><TD>$result_list</TD></TR>
</TBODY></TABLE></CENTER>";
}
else
echo "No Results";
}
?>

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

1.LDAP注入LDAP(LightDirectoryAccessPortocol)是基於X.500標準的輕量級目錄存取協議,提供存取目錄資料庫方法的服務和協議,常用於與目錄資料庫組成目錄服務。其中目錄是一個為查詢、瀏覽和搜尋而優化的專業分散式資料庫,它呈現樹狀結構組織數據,類似於Linux/Unix系統中的檔案目錄。公用憑證、安全金鑰、公司的實體設備資訊等修改並不頻繁的資料適合儲存在目錄中。可以將LDAP理解為一種搜尋協議,它類似於SQL,擁有查詢語法,也存在被注入攻擊的風險。 LDAP注入是指客

如果說sql注入的本質是拼接字串的話,那麼一切可以注入的本質都是拼接字串,LDAP注入作為注入的一種也不例外,更有趣一點的說它是在拼接圓括號(sql注入也拼接圓括號,但是更習慣的是說它拼接字串)。在環境配置篇裡面已經很詳細的說了bee-box中ldap環境的配置,靶場練習篇更多的是php與ldap的連接過程,中間使用的特殊函數介紹以及圓括號拼接的一些技巧。以下先說一下bwapp中ldap靶場的登入流程:首先這是一個LDAP的登入介面,URL是http://192.168.3.184/bW

WindowsServerBackup是WindowsServer作業系統自帶的功能,旨在協助使用者保護重要資料和系統配置,並為中小型和企業級企業提供完整的備份和復原解決方案。只有執行Server2022及更高版本的使用者才能使用此功能。在本文中,我們將介紹如何安裝、解除安裝或重設WindowsServerBackup。如何重置Windows伺服器備份如果您的伺服器備份遇到問題,備份所需時間過長,或無法存取已儲存的文件,那麼您可以考慮重新設定WindowsServer備份設定。要重設Windows

一、綜述依照我的學習過程來說,我必須知道我進行web攻擊的這個模型和漏洞的原理是什麼,現在我就碰到個冷門,最初見到LDAP時是某次在某國企的滲透測試中發現一個冷門(經過授權的),激起了我對它的興趣。 LDAP的概念:全名:輕量級目錄存取協定(LightweightDirectoryAccessProtocolt),特點:協定什麼的就不說了,太深奧,可以把它理解為一種儲存資料的資料庫,它的特殊之處在於它是一種樹狀的資料庫,首先這個資料庫的名字相當於樹根(即DB=dc),然後從樹根到某個葉子節點過程所經過

在使用PHP開發Web應用程式時,我們經常需要使用LDAP身份驗證來保護應用程式的存取。然而,在某些情況下,當我們嘗試使用PHP的LDAP功能來實現身份驗證時,可能會遇到以下錯誤訊息:"PHPFatalerror:Calltoundefinedfunctionldap_bind()"。這種錯誤訊息通常會在應用程式呼叫ldap_bind()函數

在發布WindowsServer的build26040版本之際,微軟公佈了該產品的官方名稱:WindowsServer2025。一同推出的,還有Windows11WindowsInsiderCanaryChannel版本的build26040。有些朋友可能還記得,多年前有人成功將WindowsNT從工作站模式轉換為伺服器模式,顯示微軟作業系統各版本之間的共通性。儘管現在微軟的伺服器作業系統版本和Windows11之間有明顯區別,但關注細節的人可能會好奇:為什麼WindowsServer更新了品牌,

如何修改nginx預設的名稱,可以稍微的偽裝一下,也可以裝x一般來說修改3個位置,一個是nginx.h、另一個是ngx_http_header_filter_module.c、還有一個ngx_http_special_response.c。提示:一般修改都是在nginx編譯之前修改,修改完了之後需要重新編譯程式碼如下:scr/core/nginx.conf#definenginx_version"1.4.7"#definenginx_ver"nginx/"n

微軟在針對桌面端發布Win11預覽版更新的同時,今天也發布了WindowsServer長期服務頻道(LTSC)預覽版Build25335。微軟和以往相同,並未公佈完整的更新日誌,甚至於沒有提供相應的部落格文章。微軟調整了WindowsServer預覽版更新日誌,讓其和Canary頻道版本相同,如果沒有引進新的內容,則不放官方部落格文章。 IT之家註:Server的品牌尚未更新,預覽版仍為WindowsServer2022。此外,微軟將這些版本稱為WindowsServervNext,而不是已經上市的W
