GroupPrincipal.Members.Remove () не работает с большой группой AD - PullRequest
5 голосов
/ 07 декабря 2009

Я использую классы пространства имен System.DirectoryServices.AccountManagement для управления членством в нескольких группах. Эти группы контролируют население нашей системы учета печати, и некоторые из них очень велики. Я сталкиваюсь с проблемой удаления любого пользователя из одной из этих больших групп. У меня есть тестовая программа, которая иллюстрирует проблему. Обратите внимание, что группа, которую я тестирую, не является вложенной, но user.IsMemberOf () также, похоже, имеет ту же проблему, тогда как GetAuthorizationGroups () правильно показывает группы, в которые входит пользователь. В рассматриваемой группе около 81 тыс. Участников, что больше, чем следовало бы, так как Remove () не работает и обычно составляет около 65 тыс.

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

using (var context = new PrincipalContext( ContextType.Domain ))
{
    using (var group = GroupPrincipal.FindByIdentity( context, groupName ))
    {
        using (var user = UserPrincipal.FindByIdentity( context, userName ))
        {
            if (user != null)
            {
                var isMember = user.GetAuthorizationGroups()
                                   .Any( g => g.DistinguishedName == group.DistinguishedName );
                Console.WriteLine( "1: check for membership returns: {0}", isMember );
                if (group.Members.Remove( user ))
                {
                    Console.WriteLine( "user removed successfully" );
                    group.Save();
                }
                else
                {
                    // do save in case Remove() is lying to me
                    group.Save();
                    Console.WriteLine( "user remove failed" );
                    var isStillMember = user.GetAuthorizationGroups()
                                            .Any( g => g.DistinguishedName == group.DistinguishedName );
                    Console.WriteLine( "2: check for membership returns: {0}", isStillMember );

                }
            }
        }
    }
}

Ответы [ 3 ]

5 голосов
/ 11 декабря 2009

Оказывается, это ошибка в коде GroupPrincipal.Members.Remove (), из-за которой удаление не удается для группы с более чем 1500 участниками. Это было исправлено в .NET 4.0 Beta 2. Я не знаю, планируют ли они перенести исправление в 2.0 / 3.x.

Обходной путь - получить базовый DirectoryEntry, а затем использовать Invoke для выполнения команды Remove для объекта IADsGroup.

 var entry = group.GetUnderlyingObject() as DirectoryEntry;
 var userEntry = user.GetUnderlyingObject() as DirectoryEntry;
 entry.Invoke( "Remove", new object[] { user.Path } );
0 голосов
/ 20 августа 2014

Этот пост помог мне указать верное направление, просто хотел добавить дополнительную информацию.

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

using (var groupEntry = new DirectoryEntry(groupLdapPath))
{
    groupEntry.Invoke("remove", new object[] { memberLdapPath });
    groupEntry.Invoke("add",    new object[] { memberLdapPath });
}

Также имейте в виду, что со стандартным атрибутом 'member' вы используетечист пользователя или группы Отличительное имя, но для вызова требуется путь с префиксом LDAP: //, в противном случае выдается неопределенное InnerException:

Exception from HRESULT: 0x80005000
0 голосов
/ 06 февраля 2014
public bool RemoveUserFromGroup(string UserName, string GroupName)
{
   bool lResult = false;
   if (String.IsNullOrEmpty(UserName) || String.IsNullOrEmpty(GroupName)) return lResult;
   try
   {
      using (DirectoryEntry dirEntry = GetDirectoryEntry())
      {
         using (DirectoryEntry dirUser = GetUser(UserName))
         {
            if (dirEntry == null || dirUser == null)
            {
               return lResult;
            }
            using (DirectorySearcher deSearch = new DirectorySearcher())
            {
               deSearch.SearchRoot = dirEntry;
               deSearch.Filter = String.Format("(&(objectClass=group) (cn={0}))", GroupName);
               deSearch.PageSize = 1000;
               SearchResultCollection result = deSearch.FindAll();
               bool isAlreadyRemoved = false;
               String sDN = dirUser.Path.Replace("LDAP://", String.Empty);
               if (result != null && result.Count > 0)
               {
                  for (int i = 0; i < result.Count; i++)
                  {
                     using (DirectoryEntry dirGroup = result[i].GetDirectoryEntry())
                     {
                        String sGrDN = dirGroup.Path.Replace("LDAP://", String.Empty);
                        if (dirUser.Properties[Constants.Properties.PROP_MEMBER_OF].Contains(sGrDN))
                        {
                           dirGroup.Properties[Constants.Properties.PROP_MEMBER].Remove(sDN);
                           dirGroup.CommitChanges();
                           dirGroup.Close();
                           lResult = true;
                           isAlreadyRemoved = true;
                           break;
                        }
                     }
                     if (isAlreadyRemoved)
                        break;
                  }
               }
            }
         }
      }
   }
   catch
   {
      lResult= false;
   }
   return lResult;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...