web-dev-qa-db-ja.com

ユーザー情報のActive Directoryをすばやく取得する方法

Active Directory からユーザー情報をクエリする方法動作するコードはありますが、本当に遅いです。 C#を使用しています。これは私が現在使用しているコードです:

    static void Main(string[] args)
    {
        SearchResultCollection sResults = null;

        try
        {
            //modify this line to include your domain name
            string path = "LDAP://EXTECH";
            //init a directory entry
            DirectoryEntry dEntry = new DirectoryEntry(path);

            //init a directory searcher
            DirectorySearcher dSearcher = new DirectorySearcher(dEntry);

            //This line applies a filter to the search specifying a username to search for
            //modify this line to specify a user name. if you want to search for all
            //users who start with k - set SearchString to "k"
            dSearcher.Filter = "(&(objectClass=user))";

            //perform search on Active Directory
            sResults = dSearcher.FindAll();

            //loop through results of search
            foreach (SearchResult searchResult in sResults)
            {
                if (searchResult.Properties["CN"][0].ToString() == "Adit")
                {
                    ////loop through the ad properties
                    //foreach (string propertyKey in
                    //searchResult.Properties["st"])
                    //{

                        //pull the collection of objects with this key name
                        ResultPropertyValueCollection valueCollection =
                        searchResult.Properties["manager"];

                        foreach (Object propertyValue in valueCollection)
                        {

                            //loop through the values that have a specific name
                            //an example of a property that would have multiple
                            //collections for the same name would be memberof
                            //Console.WriteLine("Property Name: " + valueCollection..ToString());
                            Console.WriteLine("Property Value: " + (string)propertyValue.ToString());

                            //["sAMAccountName"][0].ToString();
                        }
                    //}
                    Console.WriteLine(" ");
                }
            }
        }
        catch (InvalidOperationException iOe)
        {
            //
        }
        catch (NotSupportedException nSe)
        {
            //
        }
        finally
        {

            // dispose of objects used
            if (sResults != null)
                sResults.Dispose();

        }
        Console.ReadLine();
    }

ADからユーザー情報を取得するための高速なコードはどのようなものでしょうか?

24
Adyt

コードが遅い理由は、共通の1人のユーザーだけに興味がある場合でも、 [〜#〜] ldap [〜#〜] クエリがドメイン内のすべてのユーザーオブジェクトを取得するためです。 「Adit」の名前:

dSearcher.Filter = "(&(objectClass=user))";

そのため、最適化するには、LDAPクエリを関心のあるユーザーだけに絞り込む必要があります。

dSearcher.Filter = "(&(objectClass=user)(cn=Adit))";

さらに、完了したらこれらのオブジェクトを破棄することを忘れないでください:

  • DirectoryEntry dEntry
  • DirectorySearcher dSearcher
17
barneytron

UserPrincipal.FindByIdentity inside System.DirectoryServices.AccountManagement

using System.DirectoryServices.AccountManagement;

using (var pc = new PrincipalContext(ContextType.Domain, "MyDomainName"))
{
    var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "MyDomainName\\" + userName);
}
23
om471987

ユーザーがAD階層内のどこにいるかを知っている場合(たとえば、小さなネットワークの場合は「Users」コンテナ内にある可能性が非常に高い)、検索する代わりに、ユーザーアカウントに直接バインドすることもできます。

DirectoryEntry deUser = new DirectoryEntry("LDAP://cn=John Doe,cn=Users,dc=yourdomain,dc=com");

if (deUser != null)
{
  ... do something with your user
}

また、既に.NET 3.5を使用している場合は、非常に拡張されたSystem.DirectorySrevices.AccountManagement名前空間を、最も一般的なADオブジェクトごとに厳密に型指定されたクラスとともに使用することもできます。

// bind to your domain
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "LDAP://dc=yourdomain,dc=com");

// find the user by identity (or many other ways)
UserPrincipal user = UserPrincipal.FindByIdentity(pc, "cn=John Doe");

System.DirectoryServices.AccountManagementには多くの情報があります。トピックに関するJoe KaplanとEthan WilanskyによるMSDNのこの素晴らしい article をチェックしてください。

13
marc_s

このコードを次のように単純化できます。

        DirectorySearcher searcher = new DirectorySearcher();
        searcher.Filter = "(&(objectCategory=user)(cn=steve.evans))";

        SearchResultCollection results = searcher.FindAll();

        if (results.Count == 1)
        {
            //do what you want to do
        }
        else if (results.Count == 0)
        {
            //user does not exist
        }
        else
        {
            //found more than one user
            //something is wrong
        }

ユーザーがいる場所を絞り込むことができる場合は、searcher.SearchRootを、ユーザーが属することがわかっている特定のOUに設定できます。

ObjectCategoryはデフォルトでインデックス付けされるため、objectClassではなくobjectCategoryも使用する必要があります。

CN以外の属性での検索も検討する必要があります。たとえば、一意であることが保証されているため、ユーザー名(sAMAccountName)で検索する方が理にかなっている場合があります。

7
Steve Evans

特定の属性値を持つエントリを見つけるためにループを実行しているために、どの程度の「スローネス」が発生するかわかりませんが、フィルタをより具体的にすることでこのループを削除できます。ガイダンスについては、このページをお試しください... 検索フィルター構文

1
Handleman