Поэтому я проверяю имя пользователя, пароль и членство в активной директории:
function validate($username, $password, $groupname = null) {
if ($username && $password) {
$link = ldap_connect($domain);
if ($link) {
ldap_set_option($link, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind = ldap_bind($link, $username, $password);
if ($bind) {
if ($groupname) {
$filter = "(samAccountName=".$username.")";
$attrs = array("memberOf");
$res = ldap_search($link, $baseDN, $filter, $attrs);
$entries = ldap_get_entries($link, $res);
$isMember = false;
if ($entries && $entries[0] && $entries[0]['memberof']) {
$arr = $entries[0]['memberof'];
foreach ($arr as $key => $value) {
if ($key != 'count') {
$isMember = $isMember || preg_match("|".preg_quote($groupname)."|", $value);
}
}
}
return $isMember;
} else {
return true;
}
} else {
return false;
}
} else {
error_log("Could not connect to Active Directory");
return false;
}
} else {
error_log("Username or password missing");
return false;
}
}
Это работает правильно, но идет очень медленно, забирает целых 2 ~ 3 минуты, чтобы подтвердить, что пользователь является членом группы. Если я опускаю проверку членства в группе, она выполняется почти мгновенно. Как я могу ускорить это (без кеширования)?
так как из вопроса было неясно, шея бутылки - это функция ldap_search
которая занимает ~ 127 секунд, остальная часть программы работает менее чем за секунду. Следует также добавить, что у нас только около 20 пользователей AD и 10ish групп.
Сначала он выглядел так, как будто foreach
-loop с preg_match
внутри занимает некоторое время. Особенно, если есть много групп для проверки.
Но потом стало ясно, что в AD было всего 10 групп и около 20 пользователей, поэтому это должно было быть чем-то другим.
В конце концов, это была проблема с отсутствием тайм-аутов. Добавление ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 10);
прямо перед тем, как ldap_search()
вылечил проблему.
Похоже, что в этом конкретном случае соединение с LDAP-сервером было открыто, но LDAP-сервер не ответил правильно, и поэтому клиент ждал ответа до тех пор, пока не был достигнут тайм-аут. Установка этого тайм-аута на гораздо меньшее значение, чем значение по умолчанию (которое неопределенно), привело к тому, что ldap_search вернется намного раньше, поскольку ему больше не нужно ждать.
AFAIK это было исправлено в PHP-5.6.14 и PHP-7.0.0
preg_match
вместо strpos
не приводит к увеличению времени выполнения на десять порядков. Проблема лежит где-то в получении результатов от AD. Я просто не знал, существует ли лучший шаблон для достижения этой ldap_search
чем ldap_search
/ ldap_get_entries
.
ldap_search
и ldap_get_entries
? И имеет ли значение, устанавливаете ли вы $attrs = ['memberof']
или $attrs = []
?
$attrs
вldap_search
?