企業內部網站認證-以PHP撰寫Active Directory認證



企業內部網站認證-PHP撰寫Active Directory認證

前言

如同此文章所述,在產學期間,協助企業內部寫一個網站,免不了需要對使用者作控管、認證。一開始的方法當然就是直接於MSDB內建立使用者資料,用帳號密碼作為認證,然後以使用者種類控制權限。
不過對有一定規模的企業來說,MIS通常會透過Microsoft Active Directory來做設備、帳號的權限控管,在這種情況下,是否有需要額外建立帳號密碼就是值得思索的問題。換句話說,若能以原有AD架構作為驗證,相對帳戶管理上的麻煩就能降少。

背景介紹

Active Directory

提供wiki資料與公開的MSDN上的資料給各位參考,用比較簡單的話來說,AD是以樹狀結構資料結構來組成網路服務的資訊,最小儲存單位為物件(Object),物件則有自己的屬性(MSDNAD有的屬性介紹,可點此傳送),其主要目的為便利管理、資源分享,有許多既有的服務都可以存取使用,而根據前言所述我的目標是企業內部網站的認證機制建立,因此會以PHP為來實踐功能。

Lightweight Directory Access Protocol (LDAP)

中文翻譯為輕量級目錄存取協定,為一種具有階層識別能力的協定,在本篇以用於存取資料之用,詳細的介紹各位可以參考上述AD對此的介紹。而PHP亦有支援此功能,因此下面會針對PHP實際如何利用LDAP做到使用者認證之功能做詳細的敘述與範例的提供。

環境設定

上面提及會使用到PHP LDAP的功能,因此跟過去相同,需要到php.ini開啟,重新開啟伺服器(IIS/Apache),步驟為:
  1. ;extension = php_ldap.dll的分號(;)挪除,並儲存
  2. 確認php/ext的資料夾下有php_ldap.dll這個檔案
  3. 重新開啟伺服器 


PHP_LDAP介紹

後續我們會只用到的ldap function(LDAP有關的php介紹在此http://php.net/manual/en/book.ldap.php):
  • ldap_connect 建立與LDAP連線辨識者,用於確認指定的網域是否可行。切記,在此並未開啟連結,只是用於確認能否連結到該網域的認證伺服器。在公司內,可能為192.168.1.123這樣的位址(若知道AD架在哪台機器上),或是可以直接用網域名稱(domain name)來測試,如公司通常為:公司英文名稱.com.tw
  •  ldap_bind:以特定的RDN與密碼與LDAP資料夾建立連線,若是沒有指定RDN或密碼,會嘗試以匿名綁定。
  •  ldap_close:最終連線終止時呼叫,無須任何參數。
(若只是要認證的話可以用上述三個funciton)
(若是要取出特定篩選條件下的所有資料)


實際範例

範例一:測試與AD連線是否成功,與特定帳號、密碼與AD內設定一致。
//domain name(or URL),account,password should replace with actual string
<?php
//For testing the AD server is work or not
$ldaphost="domain name";
$ldapconn=ldap_connect($ldaphost);
if($ldapconn)
echo "Connect success<br>";
else
echo "Connect Failure";
//For simplification,you can wirte $ldapconn = ldap_connect($ldaphost)or die("Could not connect to ".$ldaphost);
//rdn:relative distinguished name
$User="account";
$ldaprdn=$User."@".$ldaphost;
$ldappass="password";
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
//Reference:http://php.net/manual/en/function.ldap-bind.php
if ($ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
echo "LDAP bind failed...";
}
}
ldap_close($ldapconn);
?>
view raw PHP_LDAP_1.php hosted with ❤ by GitHub

範例二:查找AD定義的使用者資料。
//First part,for testing the AD server is work or not
//Second part,for searching the specified CN and listing them
<?php
$ldaphost="domain name";
$ldapconn=ldap_connect($ldaphost);
if($ldapconn)
echo "Connect success<br>";
else
echo "Connect Failure";
//For simplification,you can wirte $ldapconn = ldap_connect($ldaphost)or die("Could not connect to ".$ldaphost);
//rdn:relative distinguished name
$User="account";
$ldaprdn=$User."@".$ldaphost;
$ldappass="password";
//Reference:http://php.net/manual/en/function.ldap-bind.php
if ($ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
echo "LDAP bind failed...";
}
}
//Start search some data in AD(for example the CN is the string starting from the "李")
//$base_dn,array can modify as you need
$base_dn="DC=com";
$result = ldap_search($ldapconn,$base_dn,"(CN=李*)") or die ("Error in query");
$data = ldap_get_entries($ldapconn,$result);
echo $data["count"]."行資料<br>";
$entry = ldap_first_entry($ldapconn, $result);
if ($entry)
{
$attr = array("Displayname","Name","CN","department");
do
{
foreach ($attr as $attribute)
{
$val=ldap_get_values($ldapconn, $entry, $attribute);
echo "$attribute: $val[0]";
}
echo "<hr>";
}
while ($entry = ldap_next_entry($ldapconn, $entry));
}
ldap_close($ldapconn);
?>
view raw PHP_LDAP.php hosted with ❤ by GitHub
 


留言