Не встечал ли кто хороший ldap-класс, а лучше всего, который не использует php_ldap. это было бы просто замечательно. Собираюсь делать аутентификацию через AD. В данный момент в поисках. посоветуйте, если кто сталкивался.
я делал на друпале + AD (модуль). вот основная функция аутентификации PHP: <?php function ldap_checkuser($username, $pwd) { if ( $username == '' || $pwd == '' ) return false; $g_res = ldap_connect('<адрес сервера>'); if ( $g_res == FALSE ) return false; ldap_set_option($g_res, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($g_res, LDAP_OPT_REFERRALS, 0); if ( @ldap_bind($g_res, "$username@domainname.ru", $pwd) == FALSE ) { return false; } // ищем этого юзверя в AD и забираем всю инфу о нем. $sr=ldap_search($g_res,"ou=Office,dc=domainname,dc=ru", "(samaccountname=$username)", array("*") ); $info = ldap_get_entries($g_res, $sr); $ar_res = array(); $ar_res['login'] = $username; $ar_res['pwd'] = $pwd; for ($i=0; $i<$info["count"]; $i++) { // тут в цикле обрабатывается инфа о юзвере } ldap_unbind($g_res); $g_res = 0; return true; }?> все остальное было на друпале ) не забываем, что у AD своя родная виндовая кодировка.
neyr00n все понятно. спасибо. а класс какой-нибудь найти не пытался или тут кроме этой одной процедурки больше ничего и не понадобится?
кстати насчет пхп и лдап. правильно я понимаю, что один раз в начале вся нужная инфа по пользователю скачивается из АД и сохраняется в сессию. А потом уже достается оттуда? как быть, если пользак уже зарегился и просит "открой мне то то и то то". Сначала его админы в АД добавят в нужную группу, а потом он должен будет перелогинится на сайте, чтобы информация из АД повторно считалась в сессию. Так что ли?
Можно ли сделать обращение к лдапу каждый раз при загрузке страницы? Насколько это долго. Если это соизмеримо с обращением к БД, тогда конечно нет проблем.
есть еще одна функция, которая ищет всех активных пользователей. вобщем мне только две функции понадобилось. если AD и сайт находятся на одной тачке по одному айпи, то по идее должно проходить быстро. а так по разному. лично у меня сайь т AD находятся на разных тачках, иногда коннект быстро проходит, иногда не очень ) зависимость не уловил.
neyr00n у меня тоже на разных. хотя бы потому что апач и посгрес на фрях крутится, а АД где- то, еще не знаю где, но точно на винде. Ты значит в в сессии хранишь всю инфу по пользователю?
тоже с АД какая- то лажу недавно была. очень медленно аутентификация проходила. похоже придется в сессию
neyr00n ldap_search($сid, "DC=corp,DC=te,DC=ru", "(objectclass=person)") не работает, хотя через виндовую лдап-бродилку этот запрос выдает все что положено. в чем тут может быть дело? что там про кодировки в AD, может в этом дело?
вот полный код сначала все проходит как положено PHP: $cid=ldap_connect($hostname); //resource id='3' type='ldap link' ldap_bind($cid, "CN=root,OU=Users,OU=Технокомэнерго,DC=corp,DC=te,DC=ru", $bindpw); //true потом уже идет PHP: ldap_search($сid, "DC=corp,DC=te,DC=ru", "(objectclass=person)")// тут false
я так думаю, тебе надо указать где именно искать, например : ou=Users, по умолчанию там находятся все пользователи AD. плюс, вместо objectClass вставь например 'samaccountname=*' (для пробы). и добавь array("*") (фильтр полей, которые будут взяты из AD): PHP: <?php // ищем все записи, которые находятся в "директории" Users. ldap_search($сid, "ou=Users,DC=corp,DC=te,DC=ru", "(samaccountname=*)", array("*")); ?> upd. в твоем случае в baseDN еще можно добавить "OU=Технокомэнерго". я строчку для себя подбирал методом тыка %) ибо вводную документашку по AD я чет непонял вообще. слишком много умных слов )) почти. пришлось извратится и при авторизации смотреть, ести ли такой опльзователь в локальной базе пользователей друпала и если нету, то он создается. и далее уже внутри сайта пользователь прозрачно авторизуется. так что инфа храниться в локальной базе пользователей. но это имхо извращение ) про кодировку я тебя обманул. в utf AD хранит.
вот спасибо, удружил. потерял на этом часик. вообще вывод такой: все запутано и сложно. целый день убил. Хотя бы потому что никто не придупредил, что там все в утф-8, но почему- то бинарные данные переводить в вин-1251 нельзя. чтобы их привести к человеческому виду надо делать бин2хекс() от утф-ного вида. Очень плохо, что через ldap нельзя получить косвенное вхождение пользователя в группу. Например (A>B, B>C => A>C). Приходится делать несколько рекурсивных запросов к АD для того чтобы рекурсивно подниматься до самых общих групп. Вот код, может кому пригодится. И на эти десять строчек потратил целый день. Все потому что нет нормальных классов для ЛДАП. Я использовал класс LDAP который нарыл в гугле http://www.ypass.net/software/php_ldap/ класс отстойный, потому что нет исключений. везде приходится писать кучи ифов и вообще кривой. достаточно заглянуть в конструктор, так что я его немного обернул. PHP: class ADUser extends User{ /** * * @var LDAPEx */ public $ldap; function login($name, $password) { $userDomane= LDAP_USER_DOMAIN; $this->ldap= new LDAPEx(iconv("Windows-1251", "UTF-8", "{$name}@{$userDomane}"), iconv("Windows-1251", "UTF-8", $password)); $this->ldap->search($this->ldap->win2utf("(&(objectclass=person)(sAMAccountName={$name}))")); $attrs= $this->ldap->fetch(); //id $this->id= bin2hex(($attrs['objectSid'][0])); //роли $this->property['roleeuserr']= array(); if (isset($attrs['memberOf'])) for($i=0; $i< $attrs['memberOf']['count']; $i++){ $this->memberOf($this->ldap->utf2win($attrs['memberOf'][$i])); } //дисконект $this->ldap->disconnect(); } /** * рекурсивно устанавливает роль и все роли в которые она входит * * @param $path путь до роли в формате ldap */ function memberOf($path) { $this->ldap->search($this->ldap->win2utf("(&(distinguishedName={$path}))")); $attrs= $this->ldap->fetch(); //id // echo $this->ldap->utf2win($attrs['name'][0]).': '.bin2hex($attrs['objectGUID'][0]).'<br>'; $this->property['roleeuserr'][]= bin2hex($attrs['objectGUID'][0]); //найти родительские роли if (isset($attrs['memberOf'])) for($i=0; $i< $attrs['memberOf']['count']; $i++) $this->memberOf($this->ldap->utf2win($attrs['memberOf'][$i])); } } а использовать его теперь так PHP: //LDAP /* * The hostname of the LDAP server. It may also be a space separated * list of LDAP servers */ define("LDAP_HOSTNAME", "9.0.11.177"); /* * The BASE DN of your ldap server. (if you don't know what it is, * you should check your slapd.conf file) */ define("LDAP_BASEDN", "DC=corp,DC=te,DC=ru"); /* * The BIND DN for your ldap server. (if you don't know what it is, * you should check your slapd.conf file) */ define("LDAP_BINDDN", iconv("Windows-1251", "UTF-8", "torsuperuser@corp.te.ru")); /* * The BIND PW for your ldap server. (if you don't know what it is, * you should check your slapd.conf file) */ define("LDAP_BINDPW", iconv("Windows-1251", "UTF-8", "qwerty")); /* * The FULL path to the configuration file with your objectClass * definitions. This file must be readable by the process using * this class (probably your web server). Do _NOT_ make your * slapd.conf file world readable. If you have objectClass definitions * in your slapd.conf file, you should separate them into a slapd.oc.conf * file. */ define("LDAP_SLAPD_OC_CONF_PATH", "/usr/local/etc/openldap/slapd.oc.conf"); define("LDAP_USER_DOMAIN", "corp.te.ru"); $user= new ADUser(); $user->login('torsuperuser', 'qwerty'); print_r($user); Код (Text): ADUser Object ( [ldap] => LDAPEx Object ( [hostname] => 9.0.11.177 [basedn] => DC=corp,DC=te,DC=ru [binddn] => torsuperuser@corp.te.ru [bindpw] => qwerty [OCconfigFilePath] => /usr/local/etc/openldap/slapd.oc.conf [cid] => Resource id #46 [bid] => 1 [sr] => Resource id #53 [re] => Resource id #54 [error] => Success [start] => 1 [objectClasses] => Array ( ) ) [id] => 010500000000000515000000c94d7d363d787b17e77b8010a0060000 [time] => [born] => [master] => [CONT] => [VIEW] => [property] => Array ( [roleeuserr] => Array ( [0] => 710234bbc2abc148ade8c1f9b4567b24 [1] => b730b0175c9c594180e02998baa5734e [2] => 8ca0b07f4b4d4f4ba730bf05312dd597 ) ) )
салют всем! опять откопал эту тему, потому что возник новый вопрос. почему не получается прибиндиться к АД под некоторым пользователем и от его имени сменить себе же пароль? Переробовал разных userAccountControl, ничего не помогает. я пробовал делать и через ldap_modify и через ldap_mod_replace. Все время пишет одну и ту же лажу "Insufficient access". Что не так? userAccountControl: 512 userAccountControl: 513 userAccountControl: 66048
не поверишь, пришел к тому же. один в один в основном из- за того, что в АД пользака никто не запрещает удалить, а в базе с пользаком может быть связана тонна логов и еще потому что в АД негде хранить списфические данные. Сначала использовал для этого ненужные поля AD вроде "Pager", но потом решил, что это еще большее извращение. Щас при первом входе пользака создаю его локальную копию, при последующих входах, обновляю ее. И в сессии храню локальную копию.