我们有一个应用程序,使用LDAP,IP地址,通过VPN隧道,使用以下代码对远程AD进行身份验证:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ldap.Host, ldap.Path.Replace("/", ""), ContextOptions.Negotiate, UserName, Password))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(pc, domainAndUsername))
{
if (user != null)
{
SAMAccountName = user.SamAccountName;
retVal = true;
}
}
}
这适用于普通的非SSL LDAP。但是,我们遇到过需要通过SSL连接到LDAPS的情况,并且它不起作用。我在PrincipalContext构造函数上尝试了大量的变体,但是我们所做的一切都会导致连接失败,并出现此错误:
System.DirectoryServices.AccountManagement.PrincipalServerDownException: The server could not be contacted. ---> System.DirectoryServices.Protocols.LdapException: The LDAP server is unavailable.
at System.DirectoryServices.Protocols.LdapConnection.Connect()
at System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(DirectoryRequest request, Int32& messageID)
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
--- End of inner exception stack trace ---
at System.DirectoryServices.AccountManagement.PrincipalContext.ReadServerConfig(String serverName, ServerProperties& properties)
at System.DirectoryServices.AccountManagement.PrincipalContext.DoServerVerifyAndPropRetrieval()
at System.DirectoryServices.AccountManagement.PrincipalContext..ctor(ContextType contextType, String name, String container, ContextOptions options, String userName, String password)
我们知道它不是LDAP服务器本身,因为尝试通过所讨论的方法here连接没有错误。我对使用try ... catch逻辑流程并不是很满意,而且我已经读过这个方法的其他一些问题(比如没有正确地尊重证书等),所以我尝试了使用PrincipalContext使这个工作。
有人可以在这里给我一些指导吗?我在这个上发疯了。
编辑:经过一些进一步的研究,看起来这可能是自签名证书的问题。
编辑2 :将其分解为X509连锁电话后,我收到了以下特定错误:
PartialChain无法将证书链构建到受信任的根颁发机构。
考虑到这一点,您认为只需将CA添加为受信任的根,但这似乎无法解决问题。
答案 0 :(得分:2)
我想知道这个CodeProject article是否有帮助:
“最近,我遇到了使用System.DirectoryServices.DirectoryEntry连接到Novell eDirectory服务器的问题,因为证书是自签名的。当在ASP.NET应用程序中运行时,未检查机器级证书存储。因此,即使自签名证书位于受信任存储中,DirectoryEntry仍然拒绝建立连接。
对于这种情况,LdapConnection类是更好的选择,因为它允许用户手动验证证书。请注意,在Windows窗体应用程序中运行时,DirectoryEntry方法可以使用受信任的自签名证书。“
使用LdapConnection,您可以使用自己的证书身份验证,如下所示:
LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier("EDIRECTORYSERVER:636"));
con.SessionOptions.SecureSocketLayer = true;
con.SessionOptions.VerifyServerCertificate =
new VerifyServerCertificateCallback(ServerCallback);
con.Credential = new NetworkCredential(String.Empty, String.Empty);
con.AuthType = AuthType.Basic;
这样的验证回调:
public static bool ServerCallback(LdapConnection connection, X509Certificate certificate)
{
try
{
X509Certificate expectedCert =
X509Certificate.CreateFromCertFile("C:\\certificates\\certificate.cer");
if (expectedCert.Equals(certificate))
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
return false;
}
}
答案 1 :(得分:0)
由Gabriel Luci检查this answer
您确定它支持SSL并且防火墙已打开以允许该连接吗?
LDAP使用端口389.LDAPS使用端口636。
如果安装了telnet客户端,则可以使用它来检查连接:
telnet yourdomain.com 636 如果你得到一个空白的屏幕,它是有效的。如果它无法连接,它会告诉你。
如果它已打开但仍然无效,则可能是使用自签名SSL证书。检查Windows事件日志中是否存在与证书相关的错误。
我还使用Chrome查看证书。你必须像这样运行chrome:
chrome.exe --explicitly-allowed-ports = 636 然后浏览到https://yourdomain.com:636并查看它是否为您提供任何证书错误。然后你就可以看到证书了。如果出现问题,您可以导入证书并明确信任它。