Авторизация доменных пользователей на PHP
Иногда, для корпоративных порталов, актуально не заводить отдельный список пользователей, а производить авторизацию через контроллер доменов.
Для этого в PHP есть набор специальных функций Облегчённый протокол доступа к каталогам (LDAP).
В принципе там все написано, но рассмотрим простой пример. Надеюсь это будет полезно для тех, кто не особо знаком с особенностями работы контроллера домена. Здесь не будем рассматривать то, как передавать информацию серверу, просто предположим, что в POST запросе прилетают имя пользователя (username) и пароль (password)
Итак, код с комментариями:
1. Набор опций (конфиг, так сказать)
Если с хостом и портом в принципе все понятно, то я бы пояснил эти две непонятные строчки.
Русские названия специально приведены т.к. в DC (domain controller) так вполне можно называть объекты.
(в связи с этим на забываем про функцию iconv. Может пригодится.
На этом этапе структуру DC можно рассматривать как набор папок с файлами в файловой системе. Папки вложены, и так формируется пути, которые мы видим. максимальная вложенность - слева. Теперь, как он строится:
cn - это объект (файл). Пользователь, группа.
ou - это папка, конечно все можно сложить с одну папку, но в большом хаосе обычно сложно ориентироваться.
dc - имя домена. т.к. на одном сервере может быть несколько доменов. Корневая папка.
т.е в этом примере мы будем авторизовывать пользователей, которые лежат в папке (и подпапках) "midomain.ru -> Пользователи" и принадлежат к группе "Портал", лежащей в папке "mydomain.ru -> Группы"
Ну и последнее - sAMAccountName - имя пользователя до собачки (user@mydomain.ru)
2. И собственно набор функций и условий:
Тут все просто, почти до безобразия.
ldap_connect - подключаемся к серверу
ldap_bind - авторизуемся на сервере (в принципе возможно уже и этого достаточно, но... )
ldap_search - ищем этого пользователя по условию, что он является членом группы.
И пару слов про сквозную авторизацию - этот вариант не рассматриваю, т.к. передавать пароль серверу умеет только ИЕ (вроде как) и только при определенных настройках. Безопасность все-таки.
Так же хорошо бы пароль шифровать, если он летает по инету.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php //ip адрес или название сервера ldap(AD) $ldaphost = "10.10.10.10"; //или "mydomain.ru" //Порт подключения $ldapport = "389"; //Полный путь к группе которой должен принадлежать человек, //что бы пройти аутентификацию. $memberof = "cn=Портал,ou=Группы,dc=mydomain,dc=ru"; //Откуда начинаем искать $base = "ou=Пользователи,dc=mydomain,dc=ru"; //Собственно говоря фильтр по которому будем аутентифицировать пользователя $filter = "sAMAccountName="; //Ваш домен, обязательно с собакой впереди. Необходим этот параметр //для авторизации через AD, по другому к сожалению работать не будет. $domain = "@mydomain.ru"; ?> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php //Если прилетели данные пользователя, то проверить его используя LDAP if (isset($_POST['username']) && isset($_POST['password'])) { $username = $_POST['username']; $login = $_POST['login'].$domain; $password = $_POST['password']; //подсоединяемся к LDAP серверу $ldap = ldap_connect($ldaphost,$ldapport) or die("Cant connect to LDAP Server"); //Включаем LDAP протокол версии 3 ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); if ($ldap) { // Пытаемся войти в LDAP при помощи введенных логина и пароля $bind = ldap_bind($ldap,$login,$password); if ($bind) //логин и пароль подошли! { // Проверим, является ли пользователь членом указанной группы. $result = ldap_search($ldap,$base,"(&(memberOf=".$memberof.")(".$filter.$username."))"); // Получаем количество результатов предыдущей проверки $result_ent = ldap_get_entries($ldap,$result); } else { die('Вы ввели неправильный логин или пароль. попробуйте еще раз'); } } // Если пользователь найден, т.е. результатов больше 0 (1 должен быть) if ($result_ent['count'] != 0) { // тут код для запоминания авторизайии exit; } else { die('К сожалению, вам доступ закрыт'); } } ?> |
Добрый день! Не могли бы Вы все таки написать как в данном случаи использовать сквозную авторизацию? Очень надо…
@Андрей
Андрей, сквозную авторизацию можно сделать только в том случае, если пользователь будет работать через IE другие браузеры это не поддерживают. Лично я такого не делал (было не нужно), но возможно напишу статью об этом, а вообще Вам нужно капать в сторону Apache+ Kerberos + LDAP. Если сделаете это быстрее нас, пришлите решение. Удачи
Подскажите, каким образом можно в случае успешной авторизации выводить ФИО, телефон, email и т.д. с AD
Приветствую.
Примерно это должно выглядеть как то так. Это надо вставить в IF где удалась авторизация. Это кусок кода из моего скрипта где я вытаскивал все дни рождения, может половина не нужна. Сама нужная часть это:
$result_ent = ldap_get_entries($ldap,$result);
и
$result_ent[$j][‘cn’][0] — тут как раз индексы массива (cn, mail) в которых хранится инфа о пользователе.
// Получаем инфу
$result_ent = ldap_get_entries($ldap,$result);
//собираем массив
$mass = array();
for ($j=0;$j<$result_ent['count'];$j++) { if (!empty($result_ent[$j]['description'][0])) { $k++; $mass[$k]['name'] = $result_ent[$j]['cn'][0]; $mass[$k]['mail'] = $result_ent[$j]['mail'][0]; } }
Добрый день!
Можете написать часть кода где это должно быть? Чего то не понял в какую часть кода это нужно вставить…
И как сделать кнопку выхода?
@Андрей
по идеи.
при инициализации страницы открываешь сессию session start();
при удаче авторизации пишешь какубнибудь переменную в массив сессии $_Session[‘xxxxxx’]
а на кнопку выход привязываешь почистить сессию:
например в request формой передаешь logout
$_Request[‘logout’]
а потом проверяешь в начале страницы есть ли метка и если есть то закрытие сессии
if(isset($_Request[‘logout’])) session_unset();