UserPrincipals.GetAuthorizationGroups Произошла ошибка (1301) при перечислении групп. После обновления до контроллера домена 2012 сервера

Исследование:

Аналогичная проблема с обходным решением, но не реальное решение существующей проблемы

Аналогичная проблема, указывающая на обновление Microsoft End Point как на виновника

Приведенные выше ссылки являются наиболее подходящими для моей проблемы. Я также просмотрел все похожие вопросы, перечисленные в Stack Overflow при создании этого сообщения, и только вышеуказанные вопросы соответствуют моей проблеме.

Фон:

Я используюUserPrincipal.GetAuthorizationGroups для разрешений для доступа к определенной странице с IIS 7.5 на Server 2008 R2 на сайте веб-форм C # .NET 4.0 в течение 2 с половиной лет. 15 мая 2013 года мы удалили основной контроллер домена под управлением Server 2008 (не r2) и заменили его контроллером домена 2012 сервера. На следующий день мы начали получать исключение, указанное ниже.

Я использую основной контекст для проверки подлинности с помощью форм. Рукопожатие имени пользователя / пароля успешно выполнено, и файл cookie аутентификации установлен правильно, но последующий вызов основного контекста, который также вызываетUserPrincipal.GetAuthorizationGroups терпит неудачу с перерывами. Мы'Мы решили несколько проблем BPA, которые появились в контроллере домена Server 2012, но это еще не помогло решить проблему. Я также учредил cron, который работает на двух отдельных серверах. Два сервера не смогут выполнить разрешение SID группы в разное время, хотя они работают с одной и той же кодовой базой. (Среда разработки и производственная среда).

Эта проблема временно разрешается после перезагрузки веб-сервера, а также на сервере dev она решается сама по себе после 12 часов простоя. Рабочий сервер обычно перестает функционировать должным образом до перезагрузки без разрешения самого себя.

На данный момент я пытаюсь уточнить cron, нацеленный на определенные контроллеры домена в сети, а также на новый DC и использующий стандартный запрос LDAP, который в настоящее время не дает более целевые времена исключений. Так далеко мыНа одном веб-сервере мы обнаружили, что в дни, когда он выходит из строя, отсутствует шаблон, но он восстановится примерно через 12 часов. Последние результаты показывают сбой разрешения SID группы между 8 и 8 часами вечера, затем он восстанавливается, через несколько дней он выходит из строя в 8 часов вечера, восстанавливается в 8 часов утра, затем работает нормально еще 12 часов и снова выходит из строя. Мы надеемся увидеть, является ли это просто конкретной проблемой связи с сервером, или посмотреть, является ли это полным набором контроллеров домена.

Исключение:

Exception information: 
Exception type: PrincipalOperationException 
Exception message: An error (1301) occurred while enumerating the groups.  
The group's SID could not be resolved.
at System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids)
at System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr)
at System.DirectoryServices.AccountManagement.AuthZSet..ctor(Byte[] userSid, NetCred credentials, ContextOptions contextOptions, String flatUserAuthority, StoreCtx userStoreCtx, Object userCtxBase)
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p)
at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups()

Вопрос:

Учитывая приведенную выше информацию, кто-нибудь имеет представление, почему вывод из эксплуатации Windows Server 2008 (не r2) и внедрение нового DC 2012 Server может привести кUserPrincipal.GetAuthorizationGroups с ошибкой разрешения 1301 SID? Идеи по устранению возможных причин также приветствуются.

Отказ от ответственности:

Это мой первый пост в Stack Overflow, я часто исследую его, но до сих пор не участвовал в дискуссиях. Простите, если я должен был опубликовать в другом месте и не стесняйтесь указывать лучшие шаги перед публикацией.

ОБНОВЛЕНИЕ 13-ИЮНЯ-2013:

12 июня я рассмотрел возможность того, что предметы не были выброшены, что вызвало проблему. Сроки были слишком короткими, чтобы определить, исправил ли исправленный код проблему, но я буду продолжать обновлять ее по мере того, как мы будем работать над решением проблемы, так что, возможно, при любой удаче кто-то здесь сможет протянуть руку.

Оригинальный код

    public bool isGroupMember(string userName, ArrayList groupList)
    {
        bool valid = false;

            PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);

            // find the user in the identity store
            UserPrincipal user =
                UserPrincipal.FindByIdentity(
                    ctx,
                    userName);

            // get the groups for the user principal and
            // store the results in a PrincipalSearchResult object
            PrincipalSearchResult groups =
                user.GetAuthorizationGroups();

            // display the names of the groups to which the
            // user belongs
            foreach (Principal group in groups)
            {
                foreach (string groupName in groupList)
                {
                    if (group.ToString() == groupName)
                    {
                        valid = true;
                    }
                }

            }
        return valid;
    }

Обновленный код

        public bool isGroupMember(string userName, ArrayList groupList, string domain_server)
        {
        bool valid = false;

            try
            {

                using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
                {

                    // find the user in the identity store
                    UserPrincipal user =
                        UserPrincipal.FindByIdentity(
                            ctx,
                            userName);

                    try
                    {
                        // get the groups for the user principal and
                        // store the results in a PrincipalSearchResult object
                        using (PrincipalSearchResult groups = user.GetAuthorizationGroups())
                        {
                            // display the names of the groups to which the
                            // user belongs

                            foreach (Principal group in groups)
                            {
                                foreach (string groupName in groupList)
                                {

                                    if (group.ToString() == groupName)
                                    {
                                        valid = true;
                                    }
                                }

                                group.Dispose();

                            }
                        }//end using-2
                    }
                    catch
                    {
                        log_gen("arbitrary info");
                        return false;
                    }
                }//end using-1
            }
            catch
            {
                log_gen("arbitrary info");
                return false;
            }

        return valid;

    }
 Pynt12 июн. 2013 г., 18:58
Обновить: Может быть проблема с неиспользованием PrincipalSearchResult. Хотя я'Я не уверен, почему это было бы проблемой через два года. Я'В настоящее время я включаю элементы iEnumerable в операторы [using], пытаясь отследить проблемы с помощью perfmon.Ресурс по утечке
 John Reilly22 дек. 2013 г., 12:01
Спасибо, что дали мне знать.
 Pynt20 июн. 2013 г., 13:59
Обновить:  Сервер разработки был стабильным в течение 8 дней, в отличие от отключения каждые несколько дней. Производственный сервер все еще работает ужасно. 12-часовое окно сбоя все еще остается сильным. Вчера, в 7:48 утра, была произведена перезагрузка для восстановления работоспособности примерно через 12 часов, в 19:54, что снова вызвало ошибку.хлопает черепом по столу
 Pynt27 июн. 2013 г., 14:54
Обновить: Я, очевидно, неЯ не знаю достаточно о Perfmon, чтобы собрать любую полезную информацию, за исключением того факта, что все выглядит стабильно. Размеры кучи / Коллекции / Виртуальные & Частный байт среди нескольких других наборов, которые были проверены. До сих пор нет видимой причины сбоя перечисления SID. При развертывании нового проекта в среде Dev нам пришлось установить .NET 4.5, у меня был проблеск надежды на то, что, возможно, эта незначительная подстройка облегчит проблему. Это не так. Вскоре мы раскручиваем среду разработки для Server 2012, чтобы посмотреть, не испытывает ли она те же проблемы.
 John Reilly18 дек. 2013 г., 11:57
Привет @Pynt, мыМы только что столкнулись с той же проблемой, что и вы, и перешли с 2012 года в качестве временного решения. Мне было просто интересно, если у вас есть что-то еще с этой проблемой, кроме вашего обходного пути?
 Pynt18 дек. 2013 г., 17:25
@Johnny Reilly, Нет прогресса, чтобы сообщить о других возможностях, кроме следующих двух ответов. Я'Я нахожусь в положении со слишком многими обязанностями и не хватает человеко-часов или помогать прогрессировать в этой ситуации из-за функциональности работы вокруг. У меня есть крайний срок 1 апреля, чтобы перенести наш веб-сервер на установку Core 2012, что позволит мне проверить ответ, данный Гэри Хиллом, но я надеюсь, что это будет сделано задолго до этого времени. Извините, у меня нет ничего нового, чтобы добавить в это время.
 Pynt19 июн. 2013 г., 15:39
Обновить: Рефакторинг основного кода, так как я узнаю больше о правильной утилизации. Я'Я все еще новичок в C # и унаследовал этот проект, так что неплохо бы обновить. Проблема все еще происходит, и яЯ все еще оптимизирую код, надеясь на лучшее. В какой-то момент я вернусь к обновлениям .NET, которые были установлены 15 мая, и посмотрю, все ли сгладится, но сейчас яЯ буду продолжать исправлять плохо реализованный код.
 Pynt15 июл. 2013 г., 14:42
Обновить: На данный момент проблема находится на заднем плане, в то время как новые функциональные возможности добавлены на сайт. Мы'Мы создали обходную систему, перечисленную в самой верхней части вопроса, но все еще имеют проблемный код, работающий в фоновом режиме для отслеживания сбоев, и вернемся к решению этой проблемы, когда позволит время.
 Pynt17 июн. 2013 г., 19:32
Обновить: Все еще было несколько битов кода, которые не были должным образом утилизированы. Обновлено сегодня и будет продолжать следить за проблемой. Ошибка перечисления SID группы возникала каждые 12 часов в выходные дни и устранялась каждые 12 часов. Мы'мы добавили больше переменных к проблеме, которую я ошибочно разместил как14 мая " но на самом деле началось16 мая ", множество обновлений .NET было установлено 15-го числа через обновление Windows.
 Pynt26 июн. 2013 г., 15:02
Обновление: яСейчас мы остановили обновления кода и использую perfmon, чтобы понять, что делает сервер в момент сбоя, и примерно то, что происходит за 12 часов до того, как он, похоже, умрет с 12-часовым шагом. Рабочий сервер работал без проблем в течение 36 часов, пока вчерашнее обновление не вызвало перезагрузку. (ура для новой установки sccm, выполняющей обслуживание в неподходящее время, но еще одна вещь, которую нужно исправить). Завершение работы ядра началось в 16:11:34, веб-сайт снова заработал в 16:15:23. Ошибка SID снова возникла в 4:15:05. Примерно через 12 часов после обновления.
 Gregoire D.26 февр. 2014 г., 16:28
Мы получили ту же проблему несколько недель назад. Читая вашу историю и разные ответы, я могу подтвердить, что проблема, скорее всего, указана @Gary Hill ниже. У нас есть сервер dev на 2008 R2 и сервер prod в 2012 году. Однажды мы реализовали некоторые права в соответствии с группами AD. Это работало нормально в 2012 году, но наш сервер был обречен. Мы обнаружили, что когда мы внедрили новый вторичный сервер AD в 2012 году, сервер dev был связан с ним, в то время как другие серверы, связанные с первичным AD в 2008 R2, были в порядке. А также объясните некоторые проблемы, с которыми мы столкнулись между 2-м годом нашей эры.

Ответы на вопрос(10)

LDAP», используйте этот код. Потому что я'у меня были вложенные группы, яя использовал GetMembers (true) и этонемного дольше, чем GetMembers ().

https://stackoverflow.com/a/27548271/1857271

или скачать исправление здесь:http://support.microsoft.com/kb/2830145

мое решение Кажется, работает стабильно хорошо. Поскольку проблема возникает при итерации по коллекции, при итерации я использую другой подход, чтобы обработать исключение, не блокируя реальную итерацию:

private string[] GetUserRoles(string Username)
{    
    List<string> roles = new List<string>();
    try
    {
        string domain = Username.Contains("\\") ? Username.Substring(0, Username.IndexOf("\\")) : string.Empty;
        string username = Username.Contains("\\") ? Username.Substring(Username.LastIndexOf("\\") + 1) : Username;
        if (!string.IsNullOrEmpty(domain) && !string.IsNullOrEmpty(username))
        {
            PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain);
            UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, username);
            if (user != null)
            {
                PrincipalSearchResult<principal> groups = user.GetAuthorizationGroups();
                int count = groups.Count();
                for (int i = 0; i < count; i++)
                {
                    IEnumerable<principal> principalCollection = groups.Skip(i).Take(1);
                    Principal principal = null;
                    try
                    {
                        principal = principalCollection.FirstOrDefault();
                    }
                    catch (Exception e)
                    {
                        //Error handling...
                        //Known exception - sometimes AD can't query a particular group, requires server hotfix?
                        //http://support.microsoft.com/kb/2830145
                    }

                    if (principal!=null && principal is GroupPrincipal)
                    {
                        GroupPrincipal groupPrincipal = (GroupPrincipal)principal;
                        if (groupPrincipal != null && !string.IsNullOrEmpty(groupPrincipal.Name))
                        {
                            roles.Add(groupPrincipal.Name.Trim());
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        //Error handling...
    }
    return roles.ToArray();
}
</principal></principal></string></string>
 Apfelkuacha06 нояб. 2018 г., 22:40
Спасибо, вы помогли мне прочитать группы, в любом случае это было слишком медленно для пользователей с более чем 100 группами, так как потребовалось довольно много времени, чтобы возникло исключение. Я нашел другой подход и разместил его здесь:stackoverflow.com/a/53180438/9758687
 Ben Anderson23 февр. 2016 г., 22:51
Спасибо за отличное решение. Хотя я неОн не любит пустые записи, пропустит группу AD, которую не может прочитать, и продолжит работу.

такой же код, выполняемый в форме веб-сайта, который используется для поиска групп безопасности пользователей в разных доменах.

Я получаю эту точную ошибку в одном из очень больших доменов, где членство в группе может включать более 50 различных групп. Он отлично работает в лесах других доменов.

В своем исследовании я обнаружил поток, который выглядит не связанным, но на самом деле имеет ту же трассировку стека. Это для удаленного приложения, работающего на SBS. Поток упоминает, что ошибка вызвана неразрешимыми SIDS в группе. Я считаю, что это будет то, что известно какзахоронены» СВДС в активном каталоге.Смотрите тему здесь.

Эта ветка предполагает, что поиск захороненных кишок и удаление их из групп решает проблему. Возможно ли, что ошибка, которую вы получаете, заключается в том, что СВДС получают надгробие каждые 12 часов отдельным процессом, не связанным с этим? В конечном счете, я считаю, что это ошибка во фреймворке, и что метод не должен завершаться сбоем из-за захороненных / неразрешимых SIDS.

Удачи!

 Pynt26 авг. 2013 г., 23:00
Я прочитал немного о неразрешенной проблеме SID до того, как отложить эту задачу на задний план, но я вернусь к этой возможной причине в какой-то момент. К счастью для меня, мы не находимся в федеративной установке в настоящее время, поэтому беспокоиться только о 1 домене. Я неНе верю, что нашему списку объявлений потребуется много времени для проверки на потерянный SID.s. К сожалению, на данный момент у меня есть 6-месячное задание, поэтому я не знаю, когда мое свободное время позволит провести этот тест. Спасибо за предложение.

groups=UserPrincipal.GetGroups() затем возникает исключение при переборе групп.

Если кто-то хочет прочитать все группы пользователя, существует следующая возможность (которая быстрее, чем использование)GetGroups()

private IList<string> GetUserGroupsLDAP(string samAccountName)
{
    var groupList = new List<string>();
    var domainConnection = new DirectoryEntry("LDAP://" + serverName, serverUser, serverUserPassword); // probably you don't need username and password

    var samSearcher = new DirectorySearcher();
    samSearcher.SearchRoot = domainConnection;
    samSearcher.Filter = "(samAccountName=" + samAccountName + ")";

    var samResult = samSearcher.FindOne();
    if (samResult != null)
    {
        var theUser = samResult.GetDirectoryEntry();
        theUser.RefreshCache(new string[] { "tokenGroups" });

        var sidSearcher = new DirectorySearcher();
        sidSearcher.SearchRoot = domainConnection;
        sidSearcher.PropertiesToLoad.Add("name");
        sidSearcher.Filter = CreateFilter(theUser);

        foreach (SearchResult result in sidSearcher.FindAll())
        {
            groupList.Add((string)result.Properties["name"][0]);
        }
    }
    return groupList;
}

private string CreateFilter(DirectoryEntry theUser)
{
    string filter = "(|";
    foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])
    {
        var SID = new SecurityIdentifier(resultBytes, 0);
        filter += "(objectSid=" + SID.Value + ")";
    }
    filter += ")";
    return filter;
}
</string></string>

перечисление групп авторизации и исправлений, отмеченных в ответе, не относится к нашему веб-серверу.

Однако перечисление и игнорирование групп, вызывающих проблемы, работает хорошо:

private static bool UserIsMember(string usr, string grp)
{
    usr = usr.ToLower();
    grp = grp.ToLower();

    using (var pc = new PrincipalContext(ContextType.Domain, "DOMAIN_NAME"))
    {
        using (var user = UserPrincipal.FindByIdentity(pc, usr))
        {
            var isMember = false;
            var authGroups = user?.GetAuthorizationGroups().GetEnumerator();

            while (authGroups?.MoveNext() ?? false)
            {
                try
                {

                    isMember = authGroups.Current.Name.ToLower().Contains(grp);
                    if (isMember) break;
                }
                catch
                {
                    // ignored
                }
            }

            authGroups?.Dispose();
            return isMember;
        }
    }
}

это версия того же кода на VB.NET. Несколько вещей, которые вы должны сделать, прежде чем этот код сможет работать

1) Вы должны ссылаться на сборку System.DirectoryServices

2) Обязательно сдайтеИмя пользователя" переменная без домена, так что если ваш домен "ГИС» и ваше имя пользователяХусейн» Windows обычно идентифицирует вас как GIS \ Hussein. Таким образом, вы должны отправить только чисто имя пользователя "Хусейн», Я разработал чувствительные к регистру вещи.

3) Метод GetGroupsNew принимает имя пользователя и возвращает список групп

4) Метод isMemberofnew берет имя пользователя и группу и проверяет, является ли этот пользователь частью этой группы или нет, это тот, который меня интересовал.



Private Function getGroupsNew(theusername As String) As List(Of String)
    Dim lstGroups As New List(Of String)
    Try

        Dim allDomains = Forest.GetCurrentForest().Domains.Cast(Of Domain)()

        Dim allSearcher = allDomains.[Select](Function(domain)
                                                  Dim searcher As New DirectorySearcher(New DirectoryEntry("LDAP://" + domain.Name))

                                                  searcher.Filter = [String].Format("(&(&(objectCategory=person)(objectClass=user)(userPrincipalName=*{0}*)))", theusername)

                                                  Return searcher

                                              End Function)

        Dim directoryEntriesFound = allSearcher.SelectMany(Function(searcher) searcher.FindAll().Cast(Of SearchResult)().[Select](Function(result) result.GetDirectoryEntry()))

        Dim memberOf = directoryEntriesFound.[Select](Function(entry)
                                                          Using entry
                                                              Return New With { _
                                                               Key .Name = entry.Name, _
                                                               Key .GroupName = DirectCast(entry.Properties("MemberOf").Value, Object()).[Select](Function(obj) obj.ToString()) _
                                                              }
                                                          End Using

                                                      End Function)



        For Each user As Object In memberOf
            For Each groupName As Object In user.GroupName
                lstGroups.Add(groupName)
            Next
        Next

        Return lstGroups

    Catch ex As Exception
        Throw
    End Try
End Function

Private Function isMemberofGroupNew(theusername As String, thegroupname As String) As Boolean

    Try

        Dim lstGroups As List(Of String) = getGroupsNew(theusername)

        For Each sGroup In lstGroups
            If sGroup.ToLower.Contains(thegroupname.ToLower) Then Return True
        Next

        Return False


    Catch ex As Exception
        Throw
    End Try

End Function

2 года. Внезапно мой вызов user.GetAuthorizationGroups () начал сбой; Я получаю то же исключение, что и вы (ошибка 1301). Итак, я изменил его на user.GetGroups (). Это немного подействовало, а затем начало периодически переставать работатьневерное имя пользователя или пароль ", Мой последний обходной путь, кажется, исправляет это, по крайней мере, на данный момент. Вместо вызова любого из них, после создания объекта пользователя, я также создаю объект группы, по одному для каждой группы, в которой я хочу видеть, является ли пользователь членом. то естьuser.IsMemberOf (группа)», Это похоже на работу.

try
{
using (HostingEnvironment.Impersonate())
{
    using (var principalContext = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))
    {
        using (var user = UserPrincipal.FindByIdentity(principalContext, userName))
        {
            if (user == null)
            {
                Log.Debug("UserPrincipal.FindByIdentity failed for userName = " + userName + ", thus not authorized!");
                isAuthorized = false;
            }

            if (isAuthorized)
            {
                firstName = user.GivenName;
                lastName = user.Surname;

                // so this code started failing:

                // var groups = user.GetGroups();
                // adGroups.AddRange(from @group in groups where 
                // @group.Name.ToUpper().Contains("MYSEARCHSTRING") select @group.Name);

                // so the following workaround, which calls, instead, 
                // "user.IsMemberOf(group)", 
                // appears to work (for now at least).  Will monitor for issues.

                // test membership in SuperUsers
                const string superUsersGroupName = "MyApp-SuperUsers";
                using (var superUsers = GroupPrincipal.FindByIdentity(principalContext, superUsersGroupName))
                {
                    if (superUsers != null && user.IsMemberOf(superUsers))
                        // add to the list of groups this user is a member of
                        // then do something with it later
                        adGroups.Add(superUsersGroupName);                                        
                }
Решение Вопроса

и информация, которую мне удалось отследить, может оказаться полезной; как и выше, мы видели эту проблему, когда контроллер домена работает под управлением Server 2012 - сначала с развертыванием клиента, а затем реплицируется в нашей собственной сети.

После некоторых экспериментов мы обнаружили, что наш код будет нормально работать на Server 2012, но столкнулся с кодом ошибки 1301, когда клиентская система работала под управлением Server 2008. Ключевая информация о происходящем была найдена здесь:

MS блог переведен с немецкого

Исправление, указанное в ссылке ниже, исправило проблему в нашей тестовой системе

SID S-1-18-1 и SID S-1-18-2 могутбыть картированным

Надеюсь, это полезно для кого-то! Как многие отмечают, этот вызов метода выглядит довольно хрупким, и мы, вероятно, рассмотрим реализацию какого-то альтернативного подхода, прежде чем затронем другие проблемы.

Gary

 Tilo07 авг. 2014 г., 20:59
Данке, решил вопрос для меня. (Win 2008 R2 подключается к серверу Win 2012 AD)
 dnx06 мар. 2014 г., 11:43
Спасибо, что поделились исправлением! Это решает нашу проблему!
 Jeff10 янв. 2014 г., 23:02
Я протестировал это обновление для наших компьютеров с Windows 7 и обнаружил, что оно действительно решило проблему.
 Pynt16 окт. 2013 г., 22:52
Спасибо за информацию. Это было нашей последней мыслью около 27 июня, когда мы развернули среду разработки для Server 2012. К сожалению, ресурсы были перенесены в другое место, прежде чем мы смогли реализовать этот тест. Тем не менее, я полагаю, что недавние события могут направить меня обратно к переносу всего в среду 2012 года. Между вашим комментарием и вышеприведенным я полагаю, что ситуация будет решена. Я отмечу ответ, как только у меня будет время на полную проверку.

когда наша инфраструктурная команда подключила контроллер домена 2012 к сети. У нас также были DC до 2012 года, поэтому мы периодически сталкивались с этой проблемой. Мы придумали исправление, которым я хотел поделиться - оно состоит из 2 частей.

Прежде всего, установитеисправление упоминается Гари Хилл. Это решит следующую проблему:

Произошла ошибка (1301) при перечислении групп. Группа'SID не может быть разрешен.

Мы думали, что мы были свободны после установки этого исправления. Однако после его установки мы получили другую неустойчивую ошибку. Некоторые группы, которые мы допрашивали, имели нулевое значениеsAMAccountName имущество. Фактическая собственностьбыло заполнено в Active Directory, но оно неправильно возвращалось с нулевым значением API. Я предполагаю, что это ошибка где-то в Active Directory API, но я нене знаю больше, чем это.

К счастью, мы смогли обойти эту проблему, переключившись на использование группыName собственность вместоsAMAccountName имущество. Это сработало для нас. Я полагаю, чтоsAMAccountName фактически устарел и существует только по причинам обратной совместимости. В таком случае это казалось разумным изменением.

Я прилагаю урезанную версию нашегоGetRolesForUser код для демонстрации изменения на месте.

using (var context = new PrincipalContext(ContextType.Domain, _domainName))
{
    try
    {
        var p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
        if (p == null) throw new NullReferenceException(string.Format("UserPrincipal.FindByIdentity returned null for user: {0}, this can indicate a problem with one or more of the AD controllers", username));

        var groups = p.GetAuthorizationGroups();
        var domain = username.Substring(0, username.IndexOf(@"\", StringComparison.InvariantCultureIgnoreCase)).ToLower();

        foreach (GroupPrincipal group in groups)
        {
            if (!string.IsNullOrEmpty(group.Name))
            {
                var domainGroup = domain + @"\" + group.Name.ToLower();

                if (_groupsToUse.Any(x => x.Equals(domainGroup, StringComparison.InvariantCultureIgnoreCase)))
                {
                    // Go through each application role defined and check if the AD domain group is part of it
                    foreach (string role in roleKeys)
                    {
                        string[] roleMembers = new [] { "role1", "role2" };

                        foreach (string member in roleMembers)
                        {
                            // Check if the domain group is part of the role
                            if (member.ToLower().Contains(domainGroup))
                            {
                                // Cache the Application Role (NOT the AD role)
                                results.Add(role);
                            }
                        }
                    }
                }
            }

            group.Dispose();
        }
    }
    catch (Exception ex)
    {
        throw new ProviderException("Unable to query Active Directory.", ex);
    }
}

Надеюсь, это поможет.

UserPrincipal.GetAuthorizationGroups используя совершенно новый виртуальный домен разработки, который содержал 2 рабочих станции и 50 пользователей / групп (многие из которых являются встроенными). У нас была Windows Server 2012 R2 Essentials с двумя рабочими станциями Windows 8.1 Enterprise, подключенными к домену.

Мне удалось рекурсивно получить список пользователейчленство в группе с использованием следующего кода: I '

class ADGroupSearch
{
    List<string> groupNames;

    public ADGroupSearch()
    {
        this.groupNames = new List<string>();
    }

    public List<string> GetGroups()
    {
        return this.groupNames;
    }

    public void AddGroupName(String groupName)
    {
        this.groupNames.Add(groupName);
    }

    public List<string> GetListOfGroupsRecursively(String samAcctName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName);
        Principal principal = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, samAcctName);
        if (principal == null)
        {
            return GetGroups();
        }
        else
        {
            PrincipalSearchResult<principal> searchResults = principal.GetGroups();

            if (searchResults != null)
            {
                foreach (GroupPrincipal sr in searchResults)
                {
                    if (!this.groupNames.Contains(sr.Name))
                    {
                        AddGroupName(sr.Name);
                    }
                    Principal p = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, sr.SamAccountName);

                    try
                    {
                        GetMembersForGroup(p);
                    }
                    catch (Exception ex)
                    {
                        //ignore errors and continue
                    }
                }

            }
            return GetGroups();
        }

    }



    private void GetMembersForGroup(Principal group)
    {
        if (group != null && typeof(GroupPrincipal) == group.GetType())
        {
            GetListOfGroupsRecursively(group.SamAccountName);
        } 
    }

    private bool IsGroup(Principal principal)
    {
        return principal.StructuralObjectClass.ToLower().Equals("group");
    }
}
</principal></string></string></string></string>

Ваш ответ на вопрос