天天看點

php 接入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項目的根的辨識名

$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。

//連接配接到LDAP

$connect_id = ldap_connect($LDAP_SERVER[$SERVER_ID]);

?>

在我們的例子中,“$connect_id”是連接配接的識别号,$LDAP_SERVER是可能的ldap伺服器數組,

而$SERVER_ID是由搜尋表格得到的LDAP伺服器變量。

如果連接配接成功,處理查詢:

如果連接配接成功的話,我們将得到一個有效的LDAP連接配接識别号,這樣我們就可以處理查詢。

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] = "[email protected]"

$result_array[1]["cn"] [0] = "Michael Reynolds"

["dn"] [0] = "uid=michael,dc=spinweb.net"

["givenname"][0] = "Michael"

["sn"] [0] = "Reynolds"

["mail"] [0] = "[email protected]"

資料以這種格式存放的原因是每個屬性都可能有超過一個值(象樹的結構)。例如,如果我的名

字是‘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] = "[email protected]"

在我們的搜尋中,我們隻關心每個屬性的首個值,是以除了dn隻有一個值外,其它我們隻使用每

個屬性中序号為0的值。以下就是屬性和它們含義的簡單清單:

"cn" = Common Name

"dn" = Distinguished Name

"givenname" = First Name

"sn" = Last Name

"mail" = Email位址

//如果搜尋成功,将結果排序

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 .= " 

\n";

}

elseif($dn && $cn && $email)

{

$result_list .= "$cn";

$result_list .= " $email

\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的連接配接。

//關閉連接配接

ldap_close($connect_id);

?>

定制搜尋界面的HTML表格:

最後,我們要定制搜尋用的HTML表格,它是用來給使用者執行搜尋的。

//定制表格

echo " 

";

echo "Search in:"; //循環以建立SELECT選項for($i=0;

$i echo "".

$LDAP_NAME[$i]."";

echo "";

echo "Search for:";

echo "";

echo "(You can use * for wildcard searches, ex. * Stanley will find

all Stanleys)";

echo "

";

?>

代碼中的$PHP_SELF是一個全局的常量,代表的是腳本頁面自身,其中的循環是用來通過我們的$LDAP_NAME變量建立SELECT選項。

顯示結果:

現在所有的工作已經完成了,我們将列印出結果集。如果沒有符合的結果,将會顯示"No Results"的資訊。

//顯示結果

if($result_list)

{

echo " 

BGCOLOR=\"#FFFFEA\" WIDTH=\"450\"> 

$result_list ";

}

else

echo "No Results";

?>

源代碼

以下是完整的源代碼,隻要将它剪切并粘貼到一個HTML文檔,就可以嘗試一下了。

$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);