如何验证通过LDAP + SSL的Active Directory creds?如何验证通过LDAP

2019-05-16 21:36发布

我试图使用.NET 3.5 System.DirectoryServices.AccountManagement命名空间通过SSL加密的LDAP连接来验证用户凭据对我们的Active Directory的LDAP服务器。 下面是示例代码:

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:389", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate))
{
    return pc.ValidateCredentials(_username, _password);
}

此代码通过不安全的LDAP(端口389)的罚款,但我宁愿不以明文形式传输用户名/密码组合。 但是,当我更改为LDAP + SSL(端口636),我得到以下异常:

System.DirectoryServices.Protocols.DirectoryOperationException: The server cannot handle directory requests.
  at System.DirectoryServices.Protocols.ErrorChecking.CheckAndSetLdapError(Int32 error)
  at System.DirectoryServices.Protocols.LdapSessionOptions.FastConcurrentBind()
  at System.DirectoryServices.AccountManagement.CredentialValidator.BindLdap(NetworkCredential creds, ContextOptions contextOptions)
  at System.DirectoryServices.AccountManagement.CredentialValidator.Validate(String userName, String password)
  at System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials(String userName, String password)
  at (my code)

端口636适用于其他活动,如查找非密码信息为LDAP / AD项...

UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, _username)

...所以我知道这是不是我的LDAP服务器的SSL设置,因为它的工作原理基于SSL的其他查询。

有没有人得到的ValidateCredentials(...)调用通过SSL工作? 你能解释一下? 还是有另一种/更好的方式来验证安全AD / LDAP凭证?

Answer 1:

我能够验证使用凭据System.DirectoryServices.Protocols命名空间的感谢,向同事。 下面的代码:

// See http://support.microsoft.com/kb/218185 for full list of LDAP error codes
const int ldapErrorInvalidCredentials = 0x31;

const string server = "sd.example.com:636";
const string domain = "sd.example.com";

try
{
    using (var ldapConnection = new LdapConnection(server))
    {
        var networkCredential = new NetworkCredential(_username, _password, domain);
        ldapConnection.SessionOptions.SecureSocketLayer = true;
        ldapConnection.AuthType = AuthType.Negotiate;
        ldapConnection.Bind(networkCredential);
    }

    // If the bind succeeds, the credentials are valid
    return true;
}
catch (LdapException ldapException)
{
    // Invalid credentials throw an exception with a specific error code
    if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials))
    {
        return false;
    }

    throw;
}

我不激动与使用try / catch块来控制的决策逻辑,但它的作品。 :/



Answer 2:

也许这是另一种方式。 有没有在验证凭据不寻常的。 该ContextOptions必须正确设置。

默认值:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing

添加SSL:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing | ContextOptions.SecureSocketLayer

ContextOptions.Negotiate或ContextOptions.SimpleBind是必需的。 或任何你的服务器需要进行认证。 ContextOptions仅支持OR位位。

你可以尝试也直接设定ContextOptions这种方式ValidateCredentials方法。

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
{
    return pc.ValidateCredentials(_username, _password);
}

要么

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate))
{
    return pc.ValidateCredentials(_username, _password, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
}


Answer 3:

对我来说,ValidateCredentials方法工作得很好。 这个问题,我发现,是承载AD(我使用AD LDS)的服务器上。 你需要与AD实例的服务器证书关联。 所以,如果您的实例被称为“MyAD”​​(或ActiveDirectoryWebService),从列表中需要打通MMC,该“证书”模块中的管理单元,选择“服务帐户”,然后选择“MyAD”​​。 从那里,你可以添加SSL证书导入“MyAD”​​个人商店。 这终于踢了SSL加工成齿轮。

我怀疑,从我知道LdapConnection方法和你省略了回调函数,你是不是验证服务器证书的事实。 这是一个混乱的工作和ValidateCredentials做免费的。 也许不是一个大问题,但安全漏洞没有-的少。



Answer 4:

我知道这是旧的,但任何人都遇到了此再次:

PrincipalContext.ValidateCredentials(...)默认情况下,试图打开一个SSL连接( ldap_init(NULL, 636)然后设置选项LDAP_OPT_FAST_CONCURRENT_BIND

如果(可信?) 客户端证书存在,但是,LDAP连接隐含的约束和快速绑定不能再启用。 PrincipalContext不考虑这种情况下,未能用一个意想不到的DirectoryOperationException

解决方法:要支持SSL,其中可能的,但有一个后备,调用ValidateCredentials(...)使用默认选项第一(即没有选项)。 如果失败与DirectoryOperationException ,通过指定再试ContextOptions (协商|密封|签约),这是ValidateCredentials的预期内部确实LdapException反正。



文章来源: How do I validate Active Directory creds over LDAP + SSL?