Проверка Active Directory медленная в PHP

1

Поэтому я проверяю имя пользователя, пароль и членство в активной директории:

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 групп.

  • 0
    Это займет много времени, когда вы передадите пустой $attrs в ldap_search ?
  • 0
    Результат был идентичен.
Показать ещё 3 комментария
Теги:
performance
ldap
active-directory

1 ответ

1
Лучший ответ

Сначала он выглядел так, как будто 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

  • 0
    Нет, код PHP может быть медленнее, чем ваш, но все равно работает почти мгновенно. Простое использование preg_match вместо strpos не приводит к увеличению времени выполнения на десять порядков. Проблема лежит где-то в получении результатов от AD. Я просто не знал, существует ли лучший шаблон для достижения этой ldap_search чем ldap_search / ldap_get_entries .
  • 0
    Так где же узкое место? Сколько времени занимает ldap_search и ldap_get_entries ? И имеет ли значение, устанавливаете ли вы $attrs = ['memberof'] или $attrs = [] ?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню