DirectoryServices.AccountManagement“旧” 更改密码后密码仍然有效
在 Active Directory 中重置用户密码后,如果用户尝试使用旧密码登录,则以下代码将验证为 True:
Dim up As UserPrincipal = GetAdUser(objContext, arg_strBA, arg_strUsername)
If up IsNot Nothing Then
Dim valid As Boolean = up.Context.ValidateCredentials(
up.UserPrincipalName, arg_strPassword, ContextOptions.Negotiate)
If (valid) Then strReturn = up.SamAccountName
End If
我们正在使用以下代码重置密码:
Dim objUser As New DirectoryEntry(arg_strLDAPPath)
If Not objUser Is Nothing Then
objUser.AuthenticationType = AuthenticationTypes.Secure
objUser.Invoke("SetPassword", arg_strNewPW)
objUser.CommitChanges()
end if
密码重置工作正常,用户可以使用以下命令登录他们的新密码,但他们的旧密码不应仍然有效。
当上述 ValidateCredentials 适用于旧密码时,我们将凭据分配给 Web 服务调用,然后该调用会失败并出现“401:未经授权”错误。
有人见过这样的事情吗?
After resetting a users password in Active Directory, if the user tries to log in using their old password, the following code validates as True:
Dim up As UserPrincipal = GetAdUser(objContext, arg_strBA, arg_strUsername)
If up IsNot Nothing Then
Dim valid As Boolean = up.Context.ValidateCredentials(
up.UserPrincipalName, arg_strPassword, ContextOptions.Negotiate)
If (valid) Then strReturn = up.SamAccountName
End If
We are resetting the password using the following code:
Dim objUser As New DirectoryEntry(arg_strLDAPPath)
If Not objUser Is Nothing Then
objUser.AuthenticationType = AuthenticationTypes.Secure
objUser.Invoke("SetPassword", arg_strNewPW)
objUser.CommitChanges()
end if
The password reset works fine and the user can log in with their new password, but their old password should not still validate.
When the above ValidateCredentials works for the old password, we are assigning the credentials to a web service call, which then fails with a "401: Unauthorized" error.
Anyone seen anything like this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
此问题与代码无关,但罪魁祸首是 Active Directory...
请参阅 http:// support.microsoft.com/kb/906305 获取解决方案...
This issue is not related to Code but the culprit over hear is the Active directory...
Please refer http://support.microsoft.com/kb/906305 for solution...
我找到了答案这里
从链接...
“但是,重要的是 ContextOption 不确保仅使用 Kerberos。事实证明,在某些情况下(例如,如果您指定 AD 而不是本地,并且无论如何,代码都会选择进行协商,从这个意义上说,指定密封可能意味着它将使用 Kerberos,但不一定只使用 Kerberos。真正重要的标志隐藏在该标志之下。在幕后,此方法最终会建立一个 LdapConnection,设置连接的网络凭据,设置 AuthType(重要的实际标志!),最后调用 Bind() 方法建立。使用指定凭据与 AD 服务器之一建立经过身份验证的连接 问题是,当 PrimaryContext.ValidateCredentials 设置此调用时(在您的场景中),它总是设置 AuthType = Negotiate。 在这种情况下,Kerberos 实际上会被使用,并最终失败,但系统会退回到 NTLM。”
I fount the answer Here
From the link...
"However, what counts is that ContextOption does not ensure the use of Kerberos only. It turns out that under certain situations (like if you are specifying AD rather than local, and you have a sufficiently up to date server), the code chooses to do Negotiate no matter what. In that sense, specifying Sealing probably means that it will use Kerberos, but not necessarily exclusively. The flag that really matters is burried several layers under that. Under the covers, this method ends up establishing an LdapConnection, setting the network Credentials for the connection, setting that AuthType (the actual flag that matters!), and finally calling the Bind() method. The LdapConnection.Bind() method establishes an authenticated connection to one of the AD servers using the specified credentials. The problem is that when PrincipalContext.ValidateCredentials sets up this call (in your scenario), it always sets the AuthType = Negotiate. In this case, Kerberos does in fact get used, and ends up failing, but the system falls back to NTLM."
这个有效 - 请参阅下面的解决方案 - 如果您觉得这有帮助,请告诉我,因为我们的商店对于这是否是一个好的解决方案存在分歧。
以下是Active Directory允许旧密码更改后仍然有效的解决方案。 我非常希望获得关于接受此解决方案的反馈,因为它在登录身份验证期间使用 ChangePassword。 这是一件奇怪的事情,但它确实有效。 目前我们的商店没有使用这个解决方案,所以如果有人能告诉我他们是否正在使用它,我们将不胜感激。
谢谢
Ch
Active Directory 和旧密码返回有效(15 分钟到 +- 小时)。 当调用 SetPassword 或 ChangePassword 时会发生这种情况。
历史:
我发现这被称为 AD 的一项“功能”,并且在设计上内置于 AD 中,以便当用户更改密码时,有一种宽限期,允许使用这些密码的所有资源转移到新密码。
支持AD知道最新密码这一概念的AD的一个例子是在PC上更改登录密码——在这种情况下,计算机将不允许旧密码登录。 虽然我没有这个问题的答案(除了微软必须让它发挥作用之外),但我认为这并不像看起来那么简单,因为涉及到 PC 并且它也有密码。
显示 AD 中的密码更改如何持续一段时间的一个示例可能是:
使用从 Windows 7 PC 到 Windows Server 2008 R2 机器的远程桌面。 从 Windows 安全框登录,然后出现“单击确定”框,单击“确定”即可登录。现在,将您用于远程的用户的密码更改到框中(与您的 Kirkman 用户不同??),注销并登录再次使用旧密码(在 15 分钟到一小时 +- 的时间范围内)。 旧密码将使您通过“Windows 安全”框并进入“确定”框。 当您单击“确定”时,它将失败。 如果您从远程桌面重新开始并尝试使用错误的密码,您将被阻止在 Windows 安全框处,并显示消息“登录尝试失败”。 时间限制到期后,您将无法使用旧密码通过 Windows 安全框。 (确保每次都从远程桌面启动,而不是切换用户,这将按预期运行,这也表明 PC 以某种方式参与其中)。 至少它没有用户登录 - 但这确实表明(似乎是 AD)在某种程度上允许旧密码进行某种级别的身份验证。
研究:
我发现了很多关于这个问题的参考文献,只有一个潜在的解决方案,到目前为止我还无法确定我们是否可以实现它(这是严格通过 Kerberos 而不是 NTLM 进行调用的参考文献,这并不像想象的那么简单根据文档和我的研究出现)。 我发现了许多关于如何在 .NET 中与 AD 交互的链接,但没有实际的 AD 手册。
解决方案 解决方案 解决方案 - 如果您需要解决方案 解决方案 请阅读此部分!
展示:
我发现(在测试期间偶然)对 AD 的 ChangePassword 调用将不允许传递给它的 OldPassword 成功地将密码更改为新密码。 我认为这个有效的测试实际上并不为人所知,因为我没有找到任何关于它正在使用的参考。 我实际上还没有找到解决这个问题的办法。 一天早上 3:00,我意识到我可以利用 ChangePassword 的这种用法来提供此问题的解决方案 - 至少是我们可以立即使用的解决方法,直到我们确定更好的方法为止。
首先,我检查一切是否有效,并且 AD 返回密码是否有效。 然后调用 ChangePassword (username, oldpassword, newpassword),并将 oldpassword 和 newpassword 作为用户提供的密码(两者相同)。 我知道两种结果之一(可能是三种,但违反密码策略阻止其成功)将会发生。 要么旧密码很好,但由于不满足密码策略(历史记录,新密码不能是最后 N 个密码之一)而失败,或者因为旧密码不正确而失败(两者均以消息中文本的异常错误形式返回)。 我们检查最后一个条件,如果旧密码无效,我们不会让用户登录。
未来:
也许第二双眼睛会有所帮助。
我认为解决方案是模拟或 Kerberos。 我还没有成功地找到足够的解决方案。 很明显,AD 可以区分旧密码,因为 ChangePassword 可以做到这一点。 我们正在做的事情是安全的核心,所以并不是所有东西都是开放的(比如在 AD 中查看密码历史记录的能力,我还没有找到访问它的方法)。
This Works - See SOLUTION below - Please let me know if you find this helpful as our shop is divided on whether this is an OK solution.
The following is a Solution to Active Directory Allowing Old Password to work after being changed. I would very much like feedback on the acceptance of this solution as it uses the ChangePassword during the Login Authentication. This is an odd thing to do but it works. Currently our shop is not using this solution so if anyone can tell me if they are using it or not that would be appreciated.
Thank you
Ch
Active Directory and Old Passwords returning Valid (15 minutes to +- hour). This occurs when SetPassword or ChangePassword are Invoked.
History:
I find that this is called a “Feature” of AD and is by design built into AD so that when a user changes passwords there is a kind of grace period that allows all resources using those passwords to transfer over to the new one.
One example of AD that supports the concept that AD knows the latest password is that of changing a login password on a PC – in this case the computer will not allow the old password to login. While I do not have the answer to this (other than Microsoft had to get this to work) it is my opinion that this is not as simple as it may appear as the PC is involved and it has passwords on it too.
One example showing how password changes in AD do last for a time period may be:
Using Remote Desktop from a Windows 7 PC to a Windows Server 2008 R2 box. Login from the Windows Security Box then the , click OK box appears, click OK and you are logged in. Now Change your password for the user you used to Remote into the box with (different from your Kirkman user ??), logout and login again with old password (within timeframe 15 minutes to an hour +-). The old password will get you past the Windows Security box and to the OK Box. When you click OK it will then fail. If you start over from Remote Desktop and try a bad password you will be stopped at the Windows Security Box with message “The Logon attempt failed”. After the time limit expires you will not get past the Windows Security box with the old password. (make sure to start from Remote Desktop each time NOT switch users which will act as expected which also shows that the PC in involved somehow). At least it does not the user login – but this does show that (what appears to be AD) at some level allows old passwords to authenticate to some level.
Research:
I have found many references to this problem and only one potential solution that to this point I have not been able to determine if we can implement it (this is the reference to calling strictly via Kerberos and not NTLM which is not as simple as it may appear according to the documentation and my research). I have found many links to how to interact with AD in .NET but no actual AD Manual.
SOLUTION SOLUTION SOLUTION - Read this part if you want the SOlution SOLUTION!!!
Present:
I have found (by accident during testing) that the ChangePassword call to AD will not allow the OldPassword passed to it succeed in changing the password to the new password. It is my opinion that this test that does work is not actually known as I have not found any reference to it being used. I actually have not found any solution to this problem. One morning at 3:00 am I realized that I could exploit this use of ChangePassword to provide a solution to this problem – at least a work-around we can use immediately until we can determine a better approach.
First I check that everything is valid and AD returns that the password is valid. Then a call to ChangePassword (username, oldpassword, newpassword) with the oldpassword and newpassword as password provided by the user (both the same) is done. I know one of two (possibly three but the password policy violation stops it from succeeding) outcomes will happen. Either the OldPassword is good and we fail because the Password Policy is not met (history, new password cannot be one of last N passwords) or we fail because the Old Password is incorrect (both returned as Exception error with text in message). We check for this last condition and if the oldpassword is not valid we do not let the user log in.
Future:
Maybe a second set of eyes will help.
I think the solution is in Impersonation or Kerberos. I have not had success in finding out enough on either of these as solutions. It is obvious that AD can differentiate between old passwords because the ChangePassword does it. What we are doing is at the heart of security so not everything is open (like the ability to see password history in AD, I have not found a way to access it).
您是否考虑到 AD 需要长达 15 分钟的时间才能在整个网络中传播此类更改?
马克
Did you take the up to 15 minutes of time into account that AD requires to propagate changes like that throughout the network??
Marc
我假设您在客户端计算机上执行 ValidateCredentials。 如果是这种情况,则它会缓存旧的(成功的)密码。 这样做是为了使用户能够在 Active Directory 脱机或无法访问时登录。 传播更改需要一些时间。
如果您想解决这个问题,您应该在身份验证时向提供 Web 服务的服务器而不是本地客户端计算机进行身份验证。
I assume you're ValidateCredentials executes on a client machine. If that is the case, then it has the old (successful) password cached. This is done to enable users to login if the Active Directory is offline or unreachable. Propagating changes takes some time.
If you want to get around this, you should authenticate with the Server serving the Webservice at authentication time instead of the local client machine.