我有以下两种使用LDAP和LDAPS验证用户的实现,我想知道哪个更好/更正确.对于记录,这两个都适用于SSL和非SSL连接.
我也很好奇,因为在非SSL PrincipalContext版本上使用Wireshark观看时,我仍然看到端口636上的流量.在四种组合中(非SSL LdapConnection,SSL LdapConnection,非SSL PrincipalContext,SSL PrincipalContext),它是只有一个在389和636端口都有流量,而不只是一个或另一个.可能是什么导致了这个?
LDAP连接方法:
bool userAuthenticated = false; var domainName = DomainName; if (useSSL) { domainName = domainName + ":636"; } try { using (var ldap = new LdapConnection(domainName)) { var networkCredential = new NetworkCredential(username,password,domainName); ldap.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback((con,cer) => true); ldap.SessionOptions.SecureSocketLayer = useSSL; ldap.SessionOptions.ProtocolVersion = 3; ldap.AuthType = AuthType.Negotiate; ldap.Bind(networkCredential); } // If the bind succeeds,we have a valid user/pass. userAuthenticated = true; } catch (LdapException ldapEx) { // Error Code 0x31 signifies invalid credentials,anything else will be caught outside. if (!ldapEx.ErrorCode.Equals(0x31)) { throw; } } return userAuthenticated;
PrincipalContext方法:
bool userAuthenticated = false; var domainName = DomainName; if (useSSL) { domainName = domainName + ":636"; ContextOptions options = ContextOptions.SimpleBind | ContextOptions.SecureSocketLayer; using (PrincipalContext pc = new PrincipalContext(ContextType.Domain,domainName,null,options)) { userAuthenticated = pc.ValidateCredentials(username,options); } } else { using (PrincipalContext pc = new PrincipalContext(ContextType.Domain,domainName)) { userAuthenticated = pc.ValidateCredentials(username,password); } } return userAuthenticated;
解决方法
@ DTI-Matt,在上面的示例中,您使用始终返回true的VerifyServerCertificate回调.这基本上违反了通过SSL连接到LDAP的目的,因为没有执行真正的证书检查.
虽然您可以使用X509Chain和/或X509Certificate2类实现真正的证书检查,但似乎PrincipalContext会为您处理检查.
总而言之,LdapConnection和PrincipalContext都提供了非常类似的功能,通过普通或SSL连接连接到LDAP服务器.您必须为LdapConnection提供更多手写代码才能正常工作.另一方面,PrincipalContext为您提供相同的功能,只需较少的代码即可手动编写.
请注意,非SSL PrincipalContext与端口636(您的默认LDAP over SSL端口)的连接可能是由于此类尝试尽可能安全地连接的事实.