如何通过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
。