3

LDAP/AD 検索を、現在ログインしているドメインのみの検索から、AD 内のすべてのドメインの検索に拡張しようとしています。このメソッドは、クエリで文字列を受け取り、LDAPInformation オブジェクトを返します。

私が尋ねている間、この方法よりも名前を検索する良い方法はありますか? 姓で人を探す場合、ワイルドカードを使用する必要があるため、ユーザーフレンドリーではありません (例: Doe*)。

    public static LDAPInformation[] GetGlobalAddressListVIAName(string nameQuery)
    {
        var currentForest = Forest.GetCurrentForest();
        var globalCatalog = currentForest.FindGlobalCatalog();

        using (var searcher = globalCatalog.GetDirectorySearcher())
        {
            using (var entry = new DirectoryEntry(searcher.SearchRoot.Path))
            {
                searcher.Filter = "(&(mailnickname=*)(objectClass=user)(displayName=" + nameQuery + "))";
                searcher.PropertyNamesOnly = true;
                searcher.SearchScope = SearchScope.Subtree;
                searcher.Sort.Direction = SortDirection.Ascending;
                searcher.Sort.PropertyName = "displayName";
                return searcher.FindAll().Cast<SearchResult>().Select(result => new LDAPInformation(result.GetDirectoryEntry())).ToArray();
            }
        }
    }

オブジェクトは次のとおりです。

    class LDAPInformation
{
    internal LDAPInformation(DirectoryEntry entry)
    {
        //Section: HASH
        this.sAMAccountName = (string)entry.Properties["sAMAccountName"].Value;

        //Section: Email
        this.Mail = (string)entry.Properties["mail"].Value;

        //Section: Organziation
        this.Description = (string)entry.Properties["description"].Value;
        this.Company = (string)entry.Properties["company"].Value;
        this.Title = (string)entry.Properties["title"].Value;
        this.Department = (string)entry.Properties["department"].Value;

        //Section: Name
        this.DisplayName = (string)entry.Properties["displayName"].Value;
        this.FirstName = (string)entry.Properties["firstName"].Value;
        this.MiddleName = (string)entry.Properties["middleName"].Value;
        this.LastName = (string)entry.Properties["lastName"].Value;

        //Section: Address
        this.StreetAddress = (string)entry.Properties["streetAddress"].Value;
        this.City = (string)entry.Properties["city"].Value;
        this.State = (string)entry.Properties["state"].Value;
        this.PostalCode = (string)entry.Properties["postalCode"].Value;
        this.TelephoneNumber = (string)entry.Properties["telephoneNumber"].Value;
    }

    public string DisplayName
    {
        get;
        private set;
    }

    public string Mail
    {
        get;
        private set;
    }

    public string sAMAccountName
    {
        get;
        private set;
    }

    public string Description
    {
        get;
        private set;
    }

    public string Company
    {
        get;
        private set;
    }

    public string Title
    {
        get;
        private set;
    }

    public string Department
    {
        get;
        private set;
    }

    public string FirstName
    {
        get;
        private set;
    }

    public string MiddleName
    {
        get;
        private set;
    }

    public string LastName
    {
        get;
        private set;
    }

    public string StreetAddress
    {
        get;
        private set;
    }

    public string City
    {
        get;
        private set;
    }

    public string State
    {
        get;
        private set;
    }

    public string PostalCode
    {
        get;
        private set;
    }

    public string TelephoneNumber
    {
        get;
        private set;
    }
}
4

2 に答える 2

4

@Brian Desmond と @lordzero。ここでの部分には少し遅れている可能性がありますが、私は最近この種のものに取り組んでいるので、共有すると思いました.

「あなたの検索ルートは何ですか?」というあなたの質問に答えて、ロードゼロ、AD サーバーを知らなくても、AD サーバーからそれを見つけるためにできることは次のとおりです。ドメイン登録された PC は、AD インフラストラクチャ/フォレストなどを認識します。

最初に、"GC://rootDSE" の DirectoryEntry を作成し、そこからネーミング コンテキスト、rootDomainNamingContext などを抽出します。最初のルート DSE DirectoryEntry のすべての属性をダンプして、利用可能なものを確認できます。

これは、私たちが使用するディレクトリ サービス サービス プロバイダーの実装です。

これは DirectorySearcherWrapper クラスから取得されます

私はメンバーvarを持っています。そしてコンストラクタでインスタンス化します。

DirectorySearcher directorySearcher;

私の初期化方法では、これを行います

        using (DirectoryEntry directoryEntry = new DirectoryEntry(DirectoryConstants.RootDSE))
        {
            // Create a Global Catalog Directory Service Searcher
            string strRootName = directoryEntry.Properties[DirectoryConstants.RootDomainNamingContext].Value.ToString();
            using (DirectoryEntry usersBinding = new DirectoryEntry(DirectoryConstants.GlobalCatalogProtocol + strRootName))
            {
                directorySearcher.SearchRoot = usersBinding;
                directorySearcher.ClientTimeout = timeout;
                directorySearcher.CacheResults = true;
                result = true;
                initialized = true;
            }
        }

DirectoryConstants クラスのプロパティ

public static string RootDSE { get { return @"GC://rootDSE"; } }
public static string RootDomainNamingContext { get { return "rootDomainNamingContext"; } }
public static string GlobalCatalogProtocol { get { return @"GC://"; } }

これは、ドメイン登録された PC にログインしているドメイン ユーザーに対してのみ機能すると確信しています。認証はバックグラウンドで自動的に処理されます。ユーザーがローカル アカウントにログインしている場合、またはマシンがドメインにない場合、DirectoryServicesCOMException が発生する可能性が高くなります。

お役に立てれば。破棄や StyleCop/Sonar コーディング違反が気にならない場合は、「using」構造を捨ててください。

上記のコードが存在する DirectorySearcherWrapper クラスは、サービス プロバイダー コードによって使用されます。このように分離されているため、単体テストを実行するときにビルド マシンがドメインに登録される保証がないため、簡単にモック アウトできます。

...そのほとんどは、MSDN/.Net ドキュメントからのものです。

于 2012-09-20T12:31:46.500 に答える
2

グローバル カタログに対してクエリを実行するのが正しい方法です。

Ambigous Name Resolution (ANR) - http://support.microsoft.com/kb/243299を調べることをお勧めします。

于 2012-04-23T19:44:53.647 に答える