c# - PrincipalContext LDAPS 自签名证书

标签 c# ssl ldap

我们有一个应用程序使用 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 A certificate chain could not be built to a trusted root authority.

这样看来,您可能会认为这只是将 CA 添加为可信根的问题,但这似乎并没有解决问题。

最佳答案

我想知道这 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;
  }
}

关于c# - PrincipalContext LDAPS 自签名证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46738485/

相关文章:

php - SSL - 将所有 Assets 指向 https

java - Maven - 找不到 LDAP jar 文件

c# - 将字符串中的小时和分钟添加到日期时间

c# - "unknown status code: 17042 Invalid format"使用验证码时出错

c# - 如何使在我的类上使用自定义事件成为可选的?

ssl - WSO2 消息代理 - javax.net.ssl.SSLHandshakeException

java - 服务上的 SSL(在 CentOS 上)不起作用

c# - 使用 LinqToXml 使用过滤器选择唯一的 XElements(按属性)

active-directory - 获取人群

memory - 嵌入式/内存LDAP服务器解决方案