PHP 中的 Active Directory 验证速度很慢

Active Directory Validation is Slow in PHP

所以我在 Active Directory 中验证用户名、密码和组成员身份,如下所示:

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 用户和 10 个左右的组。

Ar 首先在我看来 foreach-loop 里面有 preg_match 需要一些时间。特别是如果有很多组要检查。

但后来发现 AD 中只有 10 个组和大约 20 个用户,因此必须有所不同。

最后是缺少超时的问题。在 ldap_search() 之前添加 ldap_set_option($connection, LDAP_OPT_NETWORK_TIMEOUT, 10); 可以解决问题。

在那种特殊情况下,似乎已经打开了与 LDAP 服务器的连接,但 LDAP 服务器没有正确响应,因此客户端一直在等待应答,直到超时。将此超时设置为比默认值(不确定)小得多的值会导致 ldap_search 到 return 更早,因为它不再需要等待。

据我所知,这已在 PHP-5.6.14 和 PHP-7.0.0

中修复