2011-06-03 52 views
25

我有一個Active-Directory結構,其中User對象駐留在OU中,例如IT,技術,人力資源,帳戶等。我想編寫一個PHP腳本,用AD對用戶進行身份驗證,並根據他們的組提供aproperiate Web服務。如何使用PHP ldap_search()獲取用戶OU,如果我不知道OU的基本DN

ldap_search()需要基DN。 我試着用

ldap_search($ldap, "dc=country,dc=company,dc=co,dc=uk", "(samaccountname=$username)", array("memberof")); 

搜索但是PHP提供了 「操作錯誤」。如果相反,我指定的OU

ldap_search($ldap, "ou=sales,dc=country,dc=company,dc=co,dc=uk", "(samaccountname=jake)", array("memberof")); 

然後搜索就OK了。

我可以使用通配符嗎?

在旁註中,用戶對象應該在OU中嗎?因爲我是第一個把他們搬到裏面的小白!

編輯: 隨着信用JPBlanc用於引導我在正確的方向和http://blog.redbranch.net/?p=76

的解決方案是連接並綁定之間添加2行。

ldap_connect(..) 
ldap_set_option ($ldap, LDAP_OPT_REFERRALS, 0); 
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); 
ldap_bind(..) 

感謝=)

EDIT 2 - Fullcode:

<?php 

namespace ldap; 

abstract class AuthStatus 
{ 
    const FAIL = "Authentication failed"; 
    const OK = "Authentication OK"; 
    const SERVER_FAIL = "Unable to connect to LDAP server"; 
    const ANONYMOUS = "Anonymous log on"; 
} 

// The LDAP server 
class LDAP 
{ 
    private $server = "127.0.0.1"; 
    private $domain = "localhost"; 
    private $admin = "admin"; 
    private $password = ""; 

    public function __construct($server, $domain, $admin = "", $password = "") 
    { 
     $this->server = $server; 
     $this->domain = $domain; 
     $this->admin = $admin; 
     $this->password = $password; 
    } 

    // Authenticate the against server the domain\username and password combination. 
    public function authenticate($user) 
    { 
     $user->auth_status = AuthStatus::FAIL; 

     $ldap = ldap_connect($this->server) or $user->auth_status = AuthStatus::SERVER_FAIL; 
     ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); 
     ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); 
     $ldapbind = ldap_bind($ldap, $user->username."@".$this->domain, $user->password); 

     if($ldapbind) 
     { 
      if(empty($user->password)) 
      { 
       $user->auth_status = AuthStatus::ANONYMOUS; 
      } 
      else 
      { 
       $result = $user->auth_status = AuthStatus::OK; 

       $this->_get_user_info($ldap, $user); 
      } 
     } 
     else 
     { 
      $result = $user->auth_status = AuthStatus::FAIL; 
     } 

     ldap_close($ldap); 
    } 

    // Get an array of users or return false on error 
    public function get_users() 
    {  
     if(!($ldap = ldap_connect($this->server))) return false; 

     ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); 
     ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); 
     $ldapbind = ldap_bind($ldap, $this->admin."@".$this->domain, $this->password); 

     $dc = explode(".", $this->domain); 
     $base_dn = ""; 
     foreach($dc as $_dc) $base_dn .= "dc=".$_dc.","; 
     $base_dn = substr($base_dn, 0, -1); 
     $sr=ldap_search($ldap, $base_dn, "(&(objectClass=user)(objectCategory=person)(|(mail=*)(telephonenumber=*))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))", array("cn", "dn", "memberof", "mail", "telephonenumber", "othertelephone", "mobile", "ipphone", "department", "title")); 
     $info = ldap_get_entries($ldap, $sr); 

     for($i = 0; $i < $info["count"]; $i++) 
     { 
      $users[$i]["name"] = $info[$i]["cn"][0]; 
      $users[$i]["mail"] = $info[$i]["mail"][0]; 
      $users[$i]["mobile"] = $info[$i]["mobile"][0]; 
      $users[$i]["skype"] = $info[$i]["ipphone"][0]; 
      $users[$i]["telephone"] = $info[$i]["telephonenumber"][0]; 
      $users[$i]["department"] = $info[$i]["department"][0]; 
      $users[$i]["title"] = $info[$i]["title"][0]; 

      for($t = 0; $t < $info[$i]["othertelephone"]["count"]; $t++) 
       $users[$i]["othertelephone"][$t] = $info[$i]["othertelephone"][$t]; 

      // set to empty array 
      if(!is_array($users[$i]["othertelephone"])) $users[$i]["othertelephone"] = Array(); 
     } 

     return $users; 
    } 

    private function _get_user_info($ldap, $user) 
    { 
     $dc = explode(".", $this->domain); 

     $base_dn = ""; 
     foreach($dc as $_dc) $base_dn .= "dc=".$_dc.","; 

     $base_dn = substr($base_dn, 0, -1); 

     $sr=ldap_search($ldap, $base_dn, "(&(objectClass=user)(objectCategory=person)(samaccountname=".$user->username."))", array("cn", "dn", "memberof", "mail", "telephonenumber", "othertelephone", "mobile", "ipphone", "department", "title")); 
     $info = ldap_get_entries($ldap, $sr); 

     $user->groups = Array(); 
     for($i = 0; $i < $info[0]["memberof"]["count"]; $i++) 
      array_push($user->groups, $info[0]["memberof"][$i]); 

     $user->name = $info[0]["cn"][0]; 
     $user->dn = $info[0]["dn"]; 
     $user->mail = $info[0]["mail"][0]; 
     $user->telephone = $info[0]["telephonenumber"][0]; 
     $user->mobile = $info[0]["mobile"][0]; 
     $user->skype = $info[0]["ipphone"][0]; 
     $user->department = $info[0]["department"][0]; 
     $user->title = $info[0]["title"][0]; 

     for($t = 0; $t < $info[$i]["othertelephone"]["count"]; $t++) 
       $user->other_telephone[$t] = $info[$i]["othertelephone"][$t]; 

     if(!is_array($user->other_telephone[$t])) $user->other_telephone[$t] = Array(); 
    } 
} 

class User 
{ 
    var $auth_status = AuthStatus::FAIL; 
    var $username = "Anonymous"; 
    var $password = ""; 

    var $groups = Array(); 
    var $dn = ""; 
    var $name = ""; 
    var $mail = ""; 
    var $telephone = ""; 
    var $other_telephone = Array(); 
    var $mobile = ""; 
    var $skype = ""; 
    var $department = ""; 
    var $title = ""; 

    public function __construct($username, $password) 
    {  
     $this->auth_status = AuthStatus::FAIL; 
     $this->username = $username; 
     $this->password = $password; 
    } 

    public function get_auth_status() 
    { 
     return $this->auth_status; 
    } 
} 
?> 

用法:

$ldap = new ldap\LDAP("192.168.1.123", "company.com", "admin", "mypassword"); 
$users = $ldap->get_users(); 
+2

@ LarryG.Wapnitsky我已經發布我的代碼爲我的作品在PHP 5.3。 X。希望爲你服務。 – Jake 2012-02-16 02:37:15

+0

在我發佈後大約2小時後工作。謝謝! – 2012-02-17 11:30:23

回答

22

如果嘗試在Windows上執行上述Server 2003的Active Directory或搜索,似乎必須將LDAP_OPT_REFERRALS選項設置爲0:

ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); 
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); 

沒有這個,如果您嘗試搜索整個AD(使用域的根作爲$ base_dn),您將得到「操作錯誤」。


在LDAP目錄一般任何節點可以是任何節點下(用戶是一個節點,一個OU是一個節點)。

但Active-Directory的行爲方式與SCHEMA定義對象可以在哪個容器中存在的方式不同。所以,如果你找一個用戶,允許上司是:builtinDomaindomainDNSorganizationalUnit,你可以在這裏看到下:

enter image description here

+1

謝謝,但我得到了一個不同的警告:ldap_search():搜索:部分結果和推薦收到 – Jake 2011-06-03 04:58:23

+0

我編輯答案,你可以嘗試請。 – JPBlanc 2011-06-03 06:38:05

+0

我能解決這個問題,所以我已經將你的帖子標記爲答案。另外我也編輯了我的問題。謝謝你的幫助! – Jake 2011-06-05 04:59:00