由于不同的客户环境运行相同的代码,我试图用PHP构建一个LDAP身份验证系统,该系统可以在3种模式下工作:
- 根本不使用StartTLS(当LDAP服务器更喜欢LDAPS时(
- 尝试StartTLS,但如果LDAP服务器拒绝TLS,请保持不安全状态
- 如果LDAP服务器拒绝TLS,请尝试StartTLS并中止身份验证
以下是代码的简化版本:
// ldap_connect is successful and returns $ldap
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER); // I tried ALLOW and TRY as well and got the same results
// $configStartTls contains 1, 2 or 3 (see options above)
if ($configStartTls > 1) {
$tlsOk = ldap_start_tls($ldap) || ($configStartTls === 2);
} else {
$tlsOk = true;
}
if ($tlsOk) {
// ldap_bind here
}
以下是不支持TLS的LDAP服务器的结果(ldap_start_tls
总是返回false(,对于$configStartTls
的每个值
ldap_bind
成功-OKldap_bind
失败-KO- 未尝试
ldap_bind
-OK
在情况2:
ldap_start_tls
日志";连接错误";错误代码为11- CCD_ 7日志";无法联系LDAP服务器";出现错误-1
我不明白为什么ldap_bind
在情况2中失败。就好像使用ldap_start_tls
强制使用TLS一样。我希望在发生故障后能够以非安全的方式继续与LDAP服务器通信。
失败后,我是否必须取消使用StartTLS才能实现选项2?我该怎么做?
我只需要再次执行ldap_connect
即可在不使用StartTLS的情况下重新启动。我尝试过,但失败了,只是因为我忘记在ldap_connect
和ldap_bind
之间重新应用LDAP选项,这意味着我可能在第二次尝试时使用了LDAP v2,这就是服务器拒绝它的原因
这是完整的工作代码。它包括一个不支持TLS的免费公共LDAP服务器的URI、BindDN和密码,所以任何面临同样问题的人都可以自己尝试代码并对其进行修改。只需将$startTlsMode
的值更改为任何常量即可尝试其他模式。
const TLS_NO = 1;
const TLS_OPTIONAL = 2;
const TLS_MANDATORY = 3;
$startTlsMode = TLS_OPTIONAL;
$ldap = connectAndSetOptions();
if ($startTlsMode === TLS_OPTIONAL || $startTlsMode === TLS_MANDATORY) {
$tlsOk = ldap_start_tls($ldap);
} else {
$tlsOk = true;
}
// TLS optional and StartTLS failed, start over without using StartTLS
if ($startTlsMode === TLS_OPTIONAL && !$tlsOk) {
$ldap = connectAndSetOptions();
$tlsOk = true;
}
// TLS successful or not necessary, proceed with binding
if ($tlsOk) {
$bindOK = ldap_bind($ldap, 'cn=read-only-admin,dc=example,dc=com', 'password');
echo $bindOK ? 'Bind successful' : 'Bind failed';
} else {
echo 'No bind attempt';
}
function connectAndSetOptions() {
$ldap = ldap_connect('ldap://ldap.forumsys.com:389');
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_TRY);
return $ldap;
}