2011-06-03 16 views
25

Tengo una estructura de Active Directory donde los objetos de usuario residen en la unidad organizativa, por ejemplo, TI, técnica, recursos humanos, cuentas, etc. Quiero escribir un script PHP que autentique al usuario con AD y según su grupo para proporcionar los servicios web adecuados.Cómo PHP ldap_search() para obtener la unidad organizativa de usuario si no conozco la unidad organizativa para base DN

ldap_search() requiere base DN. Traté de buscar con

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

pero PHP da "Error de funcionamiento". Si, en cambio, especifico la unidad organizativa

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

y luego la búsqueda está bien.

¿Hay algún comodín que pueda usar?

En una nota lateral, ¿los objetos del usuario deben estar en OU en absoluto? ¡Porque soy el novato que los moví adentro en primer lugar!

EDIT: Con créditos a JPBlanc para guiarme en la dirección correcta y http://blog.redbranch.net/?p=76

La solución es añadir 2 líneas entre conectar y enlazar.

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

Gracias =)

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; 
    } 
} 
?> 

Uso:

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

@ LarryG.Wapnitsky He publicado mi código que funciona para mí en PHP 5.3. X. Espero por ti – Jake

+0

lo tengo trabajando aproximadamente 2 horas después de haber publicado. ¡Gracias! –

Respuesta

22

Si intenta realizar las búsquedas en Windows 2003 Server Active Directory o por encima , parece que debe establecer la opción LDAP_OPT_REFERRALS en 0:

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

Sin esto, obtendrá "Error de operaciones" si intenta buscar el AD completo (usando la raíz del dominio como $ base_dn).


En directorios LDAP en general, cualquier nodo puede estar bajo cualquier nodo (un usuario es un nodo, un ou es un nodo).

Pero el comportamiento de Active Directory de una manera diferente, el SCHEMA define en qué contenedor puede existir un objeto. Por lo tanto, si nos fijamos para un usuario, superiores permitidos son: builtinDomain, domainDNS y organizationalUnit como se puede ver aquí debajo:

enter image description here

+1

Gracias, pero recibo una advertencia diferente: ldap_search(): Búsqueda: resultados parciales y referencia recibida – Jake

+0

I Edite la respuesta, puede intentar por favor. – JPBlanc

+0

Pude resolver el problema, así que marqué tu publicación como la respuesta ya. Además, edité mi pregunta también. ¡Gracias por tu ayuda! – Jake

Cuestiones relacionadas