Memory leaks System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity出现奇怪问题
我们正在编写一个系统,允许用户通过内部网上的web应用程序更改其帐户密码 起初,一切似乎都进展顺利。在开发过程中,可以毫无问题地更改测试帐户的密码 然而,当我们让系统上线时,我们开始遇到问题。以下是症状:Memory leaks System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity出现奇怪问题,memory-leaks,active-directory,ldap,directoryservices,account-management,Memory Leaks,Active Directory,Ldap,Directoryservices,Account Management,我们正在编写一个系统,允许用户通过内部网上的web应用程序更改其帐户密码 起初,一切似乎都进展顺利。在开发过程中,可以毫无问题地更改测试帐户的密码 然而,当我们让系统上线时,我们开始遇到问题。以下是症状: 起初,一切都很好。使用者 可以更改他们的密码 有时 在这一点上,以下错误发生在 UserPrincipal.FindByIdentity: “System.Runtime.InteropServices.COMException: 身份验证机制是 未知。” 从那时起,努力 通过网络更改密码 应
关于为什么会发生这种情况,有什么线索吗?谷歌搜索没有发现任何真正有用的东西,MSDN上的文档也没有。我注意到的第一件事是,您使用的是继承自的。我之所以这样说,是因为
Principal
类在FindByIdentity
中存在已知的内存泄漏。如果你看一下这个,你会注意到在底部,微软说:
此调用存在非托管内存泄漏
因为底层的实现
使用DirectorySearcher和
SearchResultsCollection,但没有
打电话到
SearchResultsCollection作为
文件描述了
我猜这是你的问题。内存泄漏会导致应用程序池填满,并最终导致错误,直到应用程序池重置并释放内存
当我们使用任何active directory功能时,我们使用以下方法来完成用户密码的设置:
Public Shared Function GetUserAccount(ByVal username As String) As DirectoryEntry
Dim rootPath As String = GetRootPath()
Using objRootEntry As New DirectoryEntry(rootPath)
Using objAdSearcher As New DirectorySearcher(objRootEntry)
objAdSearcher.Filter = "(&(objectClass=user)(samAccountName=" & username & "))"
Dim objResult As SearchResult = objAdSearcher.FindOne()
If objResult IsNot Nothing Then Return objResult.GetDirectoryEntry()
End Using
End Using
Return Nothing
End Function
Public Shared Sub SetPassword(ByVal username As String, ByVal newPassword As String)
Using objUser As DirectoryEntry = GetUserAccount(username)
If objUser Is Nothing Then Throw New UserNotFoundException(username)
Try
objUser.Invoke("SetPassword", newPassword)
objUser.CommitChanges()
Catch ex As Exception
Throw New Exception("Could not change password for " & username & ".", ex)
End Try
End Using
End Sub
此外,如果你想让用户直接更改密码,而不想依赖他们的诚实,你可能想考虑使用LDAP这样的<代码> CuxEpasWord < /Case>函数:
Public Shared Sub ChangePassword(ByVal username As String, ByVal oldPassword As String, ByVal newPassword As String)
Using objUser As DirectoryEntry = GetUserAccount(username)
If objUser Is Nothing Then Throw New UserNotFoundException(username)
Try
objUser.Invoke("ChangePassword", oldPassword, newPassword)
objUser.CommitChanges()
Catch ex As TargetInvocationException
Throw New Exception("Could not change password for " & username & ".", ex)
End Try
End Using
End Sub
这会强制用户在更改为新密码之前知道先前的密码
我希望这有帮助
谢谢你对ActiveDirectoryManagementAccountName有什么建议?请尝试将其设置为“域\用户名”而不仅仅是“用户名”-这在过去对我很有效。我会尝试,尽管我怀疑这是问题所在。如果错误不是断断续续的,我更可能怀疑这种性质的问题。这段代码运行良好,直到一些看似随机的东西触发了螺旋形死亡虫洞。如果帐户名有问题,我会怀疑会出现一致的错误。然而,我们谈论的是System.DirectoryServices。。。因此,任何一种令人讨厌的奇怪现象都是可能的;)肯定有帮助。我们已经安装了一个修补程序,据说它解决了FindByIdentity的一些(但不是全部)问题,现在正在测试我们的代码。虽然我们更喜欢使用ChangePassword方法,但不幸的是,我们的域中有一些有趣的东西,它们强制执行我们不想要的密码规则。SetPassword绕过这些规则。如果我们当前修复现有代码的尝试不起作用,下一步将是直接使用System.DirectoryServices(无AccountManagement内容)重写它,正如您所演示的。Nick,当我实现上述方法时,它似乎还检查域用户帐户密码策略。我想这就是它的工作原理,因为在引擎盖下,它使用相同的方法。另外,看看这篇MSDN文章:您可以看到SetPassword可以生成一个
PasswordException
。它还声明,如果新密码不满足密码复杂性要求,它将抛出此错误。希望这有帮助!在引擎盖下,ChangePassword正在调用DirectoryEntry.Invoke(“ChangePassword”,password)。SetPassword正在调用DirectoryEntry.Invoke(“SetPassword”,password)。在使用ChangePassword时,我们的策略是强制执行的(比如不允许重复使用过去的密码)。它们不使用SetPassword强制执行。使用SetPassword,如果我有正确的权限,我可以将任何人的帐户密码设置为我喜欢的任何密码。如果你看这里:你会注意到其他人也发现了这一点。MSDN文档在这方面有误导性。尼克-这是您所指的热修复程序吗?-JeffI有一个类似的问题,我已经发布了。如果你们中有人找到了解决办法。请评论这篇文章。
Public Shared Sub ChangePassword(ByVal username As String, ByVal oldPassword As String, ByVal newPassword As String)
Using objUser As DirectoryEntry = GetUserAccount(username)
If objUser Is Nothing Then Throw New UserNotFoundException(username)
Try
objUser.Invoke("ChangePassword", oldPassword, newPassword)
objUser.CommitChanges()
Catch ex As TargetInvocationException
Throw New Exception("Could not change password for " & username & ".", ex)
End Try
End Using
End Sub