2009-12-01 2 views
3

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

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

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); 
} 

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

ответ

4

Пара вещей:

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

  • во-вторых, использовать ObjectCategory вместо объектный - 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 или выше, все стало намного проще - см:

Managing Directory Security Principals in the .NET Framework 3.5