Как PHP ldap_search (), чтобы получить пользовательское подразделение, если я не знаю OU для базового DN

У меня есть структура Active Directory, в которой объекты User находятся в OU, например, IT, Technical, HR, Accounts и т. Д. Я хочу написать PHP-скрипт, который аутентифицирует пользователя с AD и в зависимости от их группы, чтобы предоставить aproperiate веб-службы ,

Для 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")); 

то поиск в порядке.

Есть ли подстановочный знак, который я могу использовать?

На стороне примечания, должны ли пользовательские объекты быть в OU вообще? Потому что я – нуб, который перенесли их внутри, в первую очередь!

EDIT: с кредитами 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 – Полный код:

 <?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(); 

Related of "Как PHP ldap_search (), чтобы получить пользовательское подразделение, если я не знаю OU для базового DN"

Если вы попытаетесь выполнить поиск в Windows 2003 Server 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-каталогах вообще любой узел может находиться под любым узлом (пользователь является узлом, au – узлом).

Но Active-Directory ведет себя иначе, чем SCHEMA определяет, в каком контейнере может существовать объект. Таким образом, если вы ищете пользователя, разрешенными builtinDomain являются: builtinDomain , domainDNS и organizationalUnit как вы можете видеть здесь:

введите описание изображения здесь