我正在尝试使用.NET System.DirectoryServices.AccountManagement
库来获取特定Active Directory用户的UserPrincipal。
我有以下代码:
PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName");
userPrincipal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
此代码作为有效的域用户运行,但是当我执行它时,我得到以下异常:
System.DirectoryServices.DirectoryServicesCOMException(0x8007052E):登录失败:未知用户名或密码错误。
有趣的是,我可以使用相同的上下文进行以下调用,而不会出现问题:
context.ValidateCredentials(username, password, ContextOptions.Negotiate)
想法?
答案 0 :(得分:12)
您需要使用带有用户名和密码的PrincipalContext
构造函数。
Validate工作的原因是因为它使用提供的凭据绑定到目录。
答案 1 :(得分:3)
听起来您拥有存储的网络凭据。在Windows中,您可以指定在尝试访问网络资源时使用其他网络凭据。通过设置错误的网络凭据,我可以重现与您所看到的完全相同的问题。
假设您的域名为yourdomain.com
,您可以告诉Windows在与任何具有足够的yourdomain.com的计算机通话时始终使用特定的用户名和密码。
=== Windows 7/2008 ===
Add a Windows credentials
=== Windows XP / 2000/2003 ===
*.yourdomain.com
control keymgr.dll
如果这确实是您面临的问题,那么简单的解决方法就是删除存储的密码。
为什么context.ValidateCredentials(用户名,密码,ContextOptions.Negotiate)有效?这只是因为您正在初始化另一个Kerberos / NTLM身份验证,因为您再次提供*.yourdomain.com
和uername
。在引擎盖下,如果选择了Kerberos,它将向域控制器发送提供的用户名和密码,并交换Kerberos TGT票证。然后,您的计算机使用此TGT票证在LDAP服务器上获取服务票证。然后,您的计算机将此服务票证发送到LDAP服务器。请注意,此服务票证不会保留在当前登录会话中。
为什么password
不起作用?
如果您没有任何存储密码,通常它应该可以工作,因为Windows将只使用当前登录用户TGT票证来交换LDAP服务器服务票证。没有涉及用户名/密码验证过程。但是,如果您的用户名密码错误,Windows会认为它不应使用当前的登录用户TGT票证。相反,它应该使用存储的网络密码获得新的TGT票证。这就是你看到UserPrincipal.FindByIdentity