如何通过LDAP + SSLvalidationActive Directory信誉?

我正在尝试使用.NET 3.5 System.DirectoryServices.AccountManagement命名空间来validation通过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)上工作正常,但我宁愿不以明文forms传输用户/传递组合。 但是,当我更改为LDAP + SSL(端口636)时,我得到以下exception:

 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。

有没有人通过SSL获得ValidateCredentials(...)调用? 你能解释一下吗? 或者是否有另一种/更好的方法可以安全地validationAD / LDAP凭据?

由于同事,我能够使用System.DirectoryServices.Protocols命名空间validation凭据。 这是代码:

 // 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块来控制决策逻辑感到很兴奋,但它的作用是什么。 :/

也许这是另一种方式。 validation凭据中没有任何exception。 ContextOptions必须正确设置。

默认值:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing

添加Ssl:

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

ContextOptions.Negotiate或ContextOptions.SimpleBind是必需的。 或者服务器执行身份validation所需的任何内容 ContextOptions仅支持OR位。

您也可以尝试在ValidateCredentials方法中以这种方式直接设置ContextOptions。

 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); } 

对我来说,ValidateCredentials方法工作得很好。 我发现问题出在托管AD的服务器上(我正在使用AD LDS)。 您需要将服务器证书与AD实例相关联。 因此,如果您的实例名为“MyAD”​​(或ActiveDirectoryWebService),则需要打开MMC,在“证书”模块中单击,选择“服务帐户”,然后从列表中选择“MyAD”​​。 从那里,您可以将SSL证书添加到“MyAD”​​个人存储中。 这终于将SSL处理推向了极致。

我怀疑,从我所知的LdapConnection方法和你省略回调函数的事实来看,你没有validation你的服务器证书。 这是一个麻烦的工作, ValidateCredentials是免费的。 可能不是什么大不了的事,但却是一个安全漏洞。

我知道这是旧的,但对于任何遇到这种情况的人来说:

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

但是,如果存在(受信任的?) 客户端证书 ,则会隐式绑定LDAP连接,并且不再启用快速绑定。 PrincipalContext不考虑这种情况,并且因意外的DirectoryOperationException而失败。

解决方法:要尽可能支持SSL,但要有后备,请先使用默认选项调用ValidateCredentials(...) (即无选项)。 如果这与DirectoryOperationException失败,请再次指定ContextOptions (Negotiate | Sealing | Signing),这是ValidateCredentials内部为预期的LdapException做的LdapException