LDAP是用來發布目錄信息到不同資源的協議,通常都是作為集中的地址本使用,但是你知道PHP如何連接LDAP服務器嗎?相信這是很多人都不了解的,現在我們就去看看。
LDAP是一個用來發布目錄信息到許多不同資源的協議。通常它都作為一個集中的地址本使用。LDAP最基本的形式是一個連接數據庫的標準方式。該數據庫為讀查詢作了優化。因此它可以很快地得到查詢結果,不過在其它方面,例如更新,就慢得多。要特別注意的是,LDAP通常作為一個hierarchal數據庫使用,而不是一個關系數據庫。因此,它的結構用樹來表示比用表格好。正因為這樣,就不能用SQL語句了。
簡單說來,LDAP是一個得到關于人或者資源的集中、靜態數據的快速方式。
我們來做這樣幾件事:
設置公共LDAP服務器的信息;創建一個LDAP查詢;連接到LDAP服務器;如果連接成功,處理查詢;格式化輸出;關閉連接;設計搜索界面的HTML表格并顯示結果。
設置公共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表格,它是用來給用戶執行搜索的。
<?php?
//定制表格
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"的信息。
<?php?
//顯示結果
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?no
看完上述內容之后你知道PHP如何連接LDAP服務器了嗎?更多詳細內容就請關注武林技術頻道。
新聞熱點
疑難解答