我有以下两个使用LDAP和LDAPS对用户进行身份验证的实现,我想知道哪个更好/更正确。对于记录,这两种工作都在SSL和非SSL连接上进行。
我也很好奇,因为当使用Wireshark观看Non-SSL PrincipalContext版本时,我仍然可以看到端口636上的流量。在这四个组合(Non-SSL LdapConnection、SSL LdapConnection、Non-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, password, options);
}
}
else
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domainName))
{
userAuthenticated = pc.ValidateCredentials(username, password);
}
}
return userAuthenticated;发布于 2014-07-23 16:40:16
@DTI,在上面的示例中,您使用始终返回VerifyServerCertificate的true回调。这在本质上违背了通过SSL连接到LDAP的目的,因为不执行真正的证书检查。
虽然您可以使用X509Chain和/或X509Certificate2类实现真正的证书检查,但似乎PrincipalContext会为您处理这些检查。
总之,LdapConnection和PrincipalContext都提供了非常相似的功能,可以通过普通或SSL连接连接到LDAP服务器。为了使LdapConnection正常工作,您必须提供更多手工编写的代码。另一方面,PrincipalContext为您提供了相同的功能,只需编写较少的代码。
请注意,通过非SSL PrincipalContext连接到端口636 (默认的LDAP在SSL端口上)可能是因为该类试图尽可能安全地连接。
发布于 2015-01-15 15:52:53
这就是我们在SSL/非SSL上工作的结果。
public bool UserValid(string username, string password, bool useSSL)
{
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); // Uses DomainName without the ":636" at all times, SSL or not.
ldap.SessionOptions.VerifyServerCertificate += VerifyServerCertificate;
ldap.SessionOptions.SecureSocketLayer = useSSL;
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, so return userAuthenticated as false.
if (!ldapEx.ErrorCode.Equals(0x31))
{
throw;
}
}
return userAuthenticated;
}
private bool VerifyServerCertificate(LdapConnection connection, X509Certificate certificate)
{
X509Certificate2 cert = new X509Certificate2(certificate);
if (!cert.Verify())
{
// Could not validate potentially self-signed SSL certificate. Prompting user to install certificate themselves.
X509Certificate2UI.DisplayCertificate(cert);
// Try verifying again as the user may have allowed the certificate, and return the result.
if (!cert.Verify())
{
throw new SecurityException("Could not verify server certificate. Make sure this certificate comes from a trusted Certificate Authority.");
}
}
return true;
}https://stackoverflow.com/questions/19596010
复制相似问题