我试图使用.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凭证?
我能够验证使用凭据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块来控制的决策逻辑,但它的作品。 :/
也许这是另一种方式。 有没有在验证凭据不寻常的。 该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);
}
对我来说,ValidateCredentials方法工作得很好。 这个问题,我发现,是承载AD(我使用AD LDS)的服务器上。 你需要与AD实例的服务器证书关联。 所以,如果您的实例被称为“MyAD”(或ActiveDirectoryWebService),从列表中需要打通MMC,该“证书”模块中的管理单元,选择“服务帐户”,然后选择“MyAD”。 从那里,你可以添加SSL证书导入“MyAD”个人商店。 这终于踢了SSL加工成齿轮。
我怀疑,从我知道LdapConnection方法和你省略了回调函数,你是不是验证服务器证书的事实。 这是一个混乱的工作和ValidateCredentials做免费的。 也许不是一个大问题,但安全漏洞没有-的少。
我知道这是旧的,但任何人都遇到了此再次:
PrincipalContext.ValidateCredentials(...)
默认情况下,试图打开一个SSL连接( ldap_init(NULL, 636)
然后设置选项LDAP_OPT_FAST_CONCURRENT_BIND
。
如果(可信?) 客户端证书存在,但是,LDAP连接隐含的约束和快速绑定不能再启用。 PrincipalContext不考虑这种情况下,未能用一个意想不到的DirectoryOperationException
。
解决方法:要支持SSL,其中可能的,但有一个后备,调用ValidateCredentials(...)
使用默认选项第一(即没有选项)。 如果失败与DirectoryOperationException
,通过指定再试ContextOptions
(协商|密封|签约),这是ValidateCredentials
的预期内部确实LdapException
反正。