Active Directory не находит всех пользователей в C#

У меня есть код, который запрашивает Active Directory для проверки существования пользователя. Я пытаюсь проверить длинный список около 1300 идентификаторов. Я попробовал несколько методов, чтобы проверить, есть ли учетная запись пользователя (LINQ to AD, DirectorySearcher (с и без родительского DirectoryEntry), а также DirectoryEntry, который ссылается на путь WinNT://). Каждый раз он вернется и скажет, что нескольких пользователей не существует. Если я жестко закодирую их идентификаторы в коде и выполняю их индивидуально, это подтверждает существование. Если я попытаюсь сделать это в цикле foreach, я получу несколько ложных негативов.

Вот код, который я использую прямо сейчас..

static string[] userIDs = new string[] "user1","user2","user3","user4","user5","user6","user7","user8"...,"user1300"};

List<string> nonExistingUsers = new List<string>();
List<string> ExistingUsers = new List<string>();
foreach (string s in userIDs)
{
 DirectorySearcher search = new DirectorySearcher();
 search.Filter = String.Format("(SAMAccountName={0})", s);
 search.PropertiesToLoad.Add("cn");
 DirectorySearcher ds = new DirectorySearcher(de, "(&(objectClass=user)(cn=" + s + "))", new string[] { "Name" }, SearchScope.Subtree);
 SearchResultCollection resultCollection = ds.FindAll();
 SearchResult result = search.FindOne();
 if (result != null)
  ExistingUsers.Add(s);
 else
  nonExistingUsers.Add(s);
}

Любые предложения или причины, почему я получаю ложные негативы?

1 ответ

Решение

Пара вещей:

  • Прежде всего, попробуйте использовать "anr=" (разрешение неоднозначных имен) в вашем фильтре LDAP - он ищет несколько атрибутов, связанных с именами, и облегчает поиск. Идентификатор пользователя может не входить в фактическое "общее имя" (CN=user1)

  • во-вторых, используйте objectCategory вместо objectClass - objectCategory имеет одно значение и индексируется и, таким образом, значительно быстрее при поиске

  • в-третьих: почему вы сначала вызываете.FindAll(), а затем.FindOne() на следующей строке? Не кажется действительно необходимым вообще....

  • WinNT: // действительно только для обратной совместимости и, если вам нужно иметь дело с локальными учетными записями компьютеров - старайтесь избегать этого всякий раз, когда это возможно, он также предоставляет гораздо меньше свойств, чем LDAP

Вот мой код, который я написал бы:

static string[] userIDs = new string[] "user1","user2","user3","user4","user5","user6","user7","user8"...,"user1300"};

DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=Users,dc=YourComp,dc=com");

List<string> nonExistingUsers = new List<string>();
List<string> ExistingUsers = new List<string>();

foreach (string s in userIDs)
{
   DirectorySearcher search = new DirectorySearcher(searchRoot);

   search.SearchScope = SearchScope.Subtree;
   search.Filter = string.Format("(&(objectCategory=person)(anr={0}))", s);

   SearchResultCollection resultCollection = ds.FindAll();

   if(resultCollection != null && resultCollection.Count > 0)
      ExistingUsers.Add(s);
   else
      nonExistingUsers.Add(s);
}

Это работает в вашем сценарии?

Кроме того, если вы используете.NET 3.5 или выше, все стало намного проще - смотрите:

Управление принципами безопасности каталогов в.NET Framework 3.5

Другие вопросы по тегам