Странная проблема с Системой. DirectoryServices. AccountManagement. UserPrincipal. FindByIdentity

Другие люди ответили на этот вопрос превосходно, и Matthias Benkard поднимает превосходное предупреждение.

НЕ ИСПОЛЬЗУЮТ КАВЫЧКУ ДЛЯ СОЗДАНИЯ СПИСКОВ, КОТОРЫЕ ВЫ ПОЗЖЕ ИЗМЕНИТЕ. Спецификация позволяет компилятору рассматривать заключенные в кавычки списки как константы. Часто, компилятор оптимизирует константы путем создавания единственной стоимости для них в памяти и затем ссылки, что единственное значение от всех местоположений, где константа появляется. Другими словами, это может рассматривать константу как анонимная глобальная переменная.

Это может вызвать очевидные проблемы. При изменении константы она может изменить другое использование той же константы в абсолютно несвязанном коде. Например, можно сравнить некоторую переменную с' (1 1) в некоторой функции, и в совершенно другой функции, запустить список с' (1 1) и затем добавить больше материала к нему. После выполнения этих функций можно найти, что первая функция не соответствует вещам правильно больше, потому что это теперь пытается сравнить переменную с' (1 1 2 3 5 8 13), который является что вторая возвращенная функция. Эти две функции абсолютно не связаны, но они имеют эффект друг на друга из-за использования констант. Еще более сумасшедшие плохие эффекты могут произойти, как совершенно нормальное повторение списка внезапно бесконечное цикличное выполнение.

кавычка Использования, когда Вам нужен постоянный список, такой что касается сравнения. Используйте список при изменении результата.

13
задан 11 December 2009 в 01:25
поделиться

1 ответ

First thing I notice is that you are using UserPrincipal.FindByIdentity which is inherited from AuthenticablePrincipal which is inherited from Principal. I say all this because the Principal class has a known memory leak in the FindByIdentity. If you have a look at this MSDN entry, you will notice at the bottom that Gary Caldwell from Microsoft said the following:

This call has an unmanaged memory leak because the underlying implemenation uses DirectorySearcher and SearchResultsCollection but does not call dispose on the SearchResultsCollection as the document describes.

I would guess that this is your issue. The memory leak causes the Application Pool to fill up and finally cause errors, until the Application Pool is reset and the memory is disposed.

When we use any active directory functions, we use the following to accomplish setting of the user's password:

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

Also, if you're wanting the users to change the passwords directly and you don't want to rely on their honesty, you might want to consider using the ChangePassword function of LDAP like this:

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

This forces the user to know the prior password before changing to the new one.

I hope this helps,

Thanks!

11
ответ дан 2 December 2019 в 01:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: