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
中修复
所以我在 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
中修复