在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:Unauthorized”错误。
有人见过这样的事吗?
由于 德克
答案 0 :(得分:5)
此问题与Code无关,但是听到的罪魁祸首是Active目录......
请参阅http://support.microsoft.com/kb/906305寻求解决方案......
答案 1 :(得分:2)
此作品 - 请参阅下面的解决方案 - 如果您觉得这有用,请告诉我们,因为我们的商店对这是否是一个好的解决方案存在分歧。
以下是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安全框和OK框。单击“确定”后,它将失败。如果从远程桌面重新开始并尝试输入错误密码,则会在Windows安全框中停止显示“登录尝试失败”消息。时间限制到期后,您将无法使用旧密码通过Windows安全框。 (确保每次不切换用户的远程桌面,这将按预期运行,这也表明涉及PC的某种方式)。至少它不是用户登录 - 但这确实表明(某些级别似乎是AD)允许旧密码在某种程度上进行身份验证。
研究: 我找到了很多关于这个问题的引用,并且只有一个可能的解决方案到目前为止我还没能确定我们是否可以实现它(这是严格通过Kerberos而不是NTLM调用的引用,这并不像它可能那么简单根据文件和我的研究显示)。我找到了很多关于如何在.NET中与AD交互的链接,但没有实际的AD手册。
解决方案解决方案 - 如果您需要SOlution解决方案,请阅读此部分! 当下: 我发现(在测试期间偶然)对AD的ChangePassword调用将不允许传递给它的OldPassword成功将密码更改为新密码。我认为,这项有效的测试实际上并不知道,因为我没有找到任何使用它的参考。我实际上还没有找到解决这个问题的方法。一天早上凌晨3点,我意识到我可以利用ChangePassword的这种方法来解决这个问题 - 至少我们可以立即使用解决方法,直到我们能够确定更好的方法。
首先,我检查一切是否有效,AD返回密码有效。然后使用oldpassword和newpassword作为用户提供的密码(两者都相同)调用ChangePassword(username,oldpassword,newpassword)。我知道其中一个(可能是三个,但密码策略违规阻止它成功)结果将会发生。 OldPassword是好的,我们失败,因为密码策略不符合(历史记录,新密码不能是最后N个密码之一)或我们失败,因为旧密码不正确(两者都作为异常错误返回消息中的文本)。我们检查最后一个条件,如果oldpassword无效,我们不允许用户登录。
未来: 也许第二组眼睛会有所帮助 我认为解决方案是模拟或Kerberos。我没有成功地找到足够的解决方案。很明显,AD可以区分旧密码,因为ChangePassword会这样做。我们正在做的是安全的核心所以不是所有东西都是开放的(就像在AD中查看密码历史的能力,我还没有找到访问它的方法)。
答案 2 :(得分:1)
我得到答案Here
从链接......
“然而,重要的是ContextOption 不确保仅使用Kerberos。事实证明,在某些情况下(如果您指定AD而不是本地,并且您已经足够最新的服务器),代码无论如何选择进行协商。从这个意义上说,指定Sealing可能意味着它将使用Kerberos,但不一定是唯一的。真正重要的标志是在其下的几层。 ,此方法最终建立一个LdapConnection,为连接设置网络凭据,设置AuthType(重要的实际标志!),最后调用Bind()方法.LdapConnection.Bind()方法建立一个经过身份验证的连接到其中一个AD服务器使用指定的凭据。问题是,当PrincipalContext.ValidateCredentials设置此调用时(在您的方案中),始终设置AuthType = Negotiate。在这种情况下,Kerberos执行事实上使用,并最终失败,但系统回到NTLM。“
答案 3 :(得分:0)
您是否考虑了AD需要在整个网络中传播更改的最多15分钟时间?
马克
答案 4 :(得分:0)
我假设您在客户端计算机上执行ValidateCredentials。如果是这种情况,那么它将缓存旧的(成功)密码。这样做是为了使用户能够在Active Directory脱机或无法访问时登录。传播变化需要一些时间。
如果您想解决此问题,您应该在身份验证时使用服务于Web服务的服务器而不是本地客户端计算机进行身份验证。