问题描述
我正在尝试使用 .NET 3.5 System.DirectoryServices.AccountManagement
命名空间来根据我们的 Active Directory LDAP 服务器通过 SSL 加密的 LDAP 连接验证用户凭据.这是示例代码:
I'm trying to use the .NET 3.5 System.DirectoryServices.AccountManagement
namespace to validate user credentials against our Active Directory LDAP server over an SSL encrypted LDAP connection. Here's the sample code:
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)时,出现以下异常:
This code works fine over unsecured LDAP (port 389), however I'd rather not transmit a user/pass combination in clear text. But when I change to LDAP + SSL (port 636), I get the following 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 条目的非密码信息...
Port 636 works for other activities, such as looking up non-password information for that LDAP/AD entry...
UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, _username)
...所以我知道这不是我的 LDAP 服务器的 SSL 设置,因为它通过 SSL 进行其他查找.
...so I know it's not my LDAP server's SSL setup, since it works over SSL for other lookups.
有没有人收到 ValidateCredentials(...)
调用以通过 SSL 工作?你能解释一下怎么做吗?或者是否有另一种/更好的方法来安全地验证 AD/LDAP 凭据?
Has anyone gotten the ValidateCredentials(...)
call to work over SSL? Can you explain how? Or is there another/better way to securely validate AD/LDAP credentials?
推荐答案
感谢一位同事,我能够使用 System.DirectoryServices.Protocols
命名空间验证凭据.代码如下:
I was able to validate credentials using the System.DirectoryServices.Protocols
namespace, thanks to a co-worker. Here's the code:
// 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 块来控制决策逻辑并不感到兴奋,但它确实有效.:/
I'm not thrilled with using a try/catch block to control decisioning logic, but it's what works. :/
这篇关于如何通过 LDAP + SSL 验证 Active Directory 凭据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!