UserPrincipal.FindByIdentity 权限
我正在尝试使用 .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)
想法?
I'm attempting to use the .NET System.DirectoryServices.AccountManagement
library to obtain the UserPrincipal for a particular Active Directory user.
I've got the following code:
PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName");
userPrincipal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
This code is running as a valid domain user, but when I execute it I get the following exception:
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.
What's interesting is that I can make the following call, using the same context, without a problem:
context.ValidateCredentials(username, password, ContextOptions.Negotiate)
Ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要使用带有用户名和密码的
PrincipalContext
构造函数。验证起作用的原因是它使用提供的凭据绑定到目录。
You need to use the the
PrincipalContext
constructor that takes username and password.The reason that Validate works is because its using the provided credentials to bind to the directory.
听起来您有存储的网络凭据。在 Windows 中,您可以指定在尝试访问网络资源时使用不同的网络凭据。我可以通过设置错误的网络凭据来重现与您所看到的完全相同的问题。
假设您的域名为
yourdomain.com
,您可以告诉 Windows 在与任何包含 yourdomain.com 的计算机进行通信时始终使用特定的用户名和密码。=== Windows 7/2008 ===
添加 Windows 凭据
*.yourdomain.com
== = Windows XP/2000/2003 ===
control keymgr.dll
* .yourdomain.com
如果这确实是您面临的问题,简单的解决方法是删除存储的密码。
为什么 context.ValidateCredentials(用户名, 密码, ContextOptions.Negotiate) 有效?这只是因为您再次提供了
用户名
和密码
,因此正在初始化另一个Kerberos/NTLM身份验证。在幕后,如果选择 Kerberos,它将向域控制器发送提供的用户名和密码,并交换 Kerberos TGT 票证。然后,您的计算机使用此 TGT 票证在 LDAP 服务器上获取服务票证。然后,您的机器会将此服务票证发送到 LDAP 服务器。请注意,此服务票证不会保留在当前登录会话中。为什么
UserPrincipal.FindByIdentity
不起作用?如果您没有任何存储的密码,通常它应该可以工作,因为 Windows 将仅使用当前登录用户 TGT 票证来交换 LDAP 服务器服务票证。不涉及用户名/密码验证过程。但是,如果您的用户名密码确实错误,Windows 会认为不应使用当前登录用户 TGT 票证。相反,它应该使用存储的网络密码获取新的 TGT 票证。这就是您看到
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): 登录失败: 未知的用户名或错误密码的原因。
It sounds like you have a stored network credentials. In Windows, you can specify to use a different network credentials when trying to reach a network resources. I can reproduce exactly the same problem as you are seeing by setting up a wrong network credentials.
Assuming your domain is called
yourdomain.com
, you can tell Windows to always use a specific username and password whenever it talks to any computers with suffice yourdomain.com.=== Windows 7/2008 ===
Add a Windows credentials
*.yourdomain.com
=== Windows XP/2000/2003 ===
control keymgr.dll
*.yourdomain.com
If this is really the problem that you are facing, the easy fix is to remove the stored passwords.
Why does context.ValidateCredentials(username, password, ContextOptions.Negotiate) work? It's simply because you are initializing another Kerberos/NTLM authentication since you provides
uername
andpassword
again. Under the hood, if Kerberos is chosen, it would send the domain controller the provided username and password and exchange for a Kerberos TGT ticket. Then, your machine get a service ticket on the LDAP server using this TGT ticket. Then, your machine will send this service ticket to the LDAP server. Note that this service ticket won't be retained in the current logon session.Why
UserPrincipal.FindByIdentity
doesn't work?If you don't have any stored password, normally it should work because Windows will just use the current logon user TGT ticket to exchange for the LDAP server service ticket. There is no username/password validation process involved. However, if you do have a bad username password, Windows would think it shouldn't use the current logon user TGT ticket. Instead, it should get a new TGT ticket using the stored network password. That's the reason you are seeing
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.