PHP串連LDAP伺服器

來源:互聯網
上載者:User
伺服器 【摘 要】 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"的資訊。

<?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 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 .= " <<A href='/"mailto:$email/"'>$email</A>
\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 "<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>";

//顯示結果
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";
}

?>



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。