.NETからActive Directoryデータにアクセス ~グループ情報の取得と表示~

3,658 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,658
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
8
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

.NETからActive Directoryデータにアクセス ~グループ情報の取得と表示~

  1. 1. .NETからActive Directoryデータにアクセス グループ情報を表示する 小山 三智男 mitchin
  2. 2. サンプルアプリケーション 2 開発環境 • OS:Windows7(x64) • IDE:Visual Studio 2010 SP1 • アプリ:Windows フォーム(.NET 4 Client Profile) Web フォーム(.NET 4) IE10 クラスライブラリ(.NET 4 Client Profile) 実行環境 • 単一ドメイン、単一サイト、単一サブネット • サーバ:Windows Server 2008 Standard SP1 (.NET 4) • IIS:Windows 認証 • Windowsクライアント:Windows 7 SP1、Windows XP SP3 • Webクライアント:IE10、IE8
  3. 3. 3 参照設定 • .NETからActive Directoryの色々な情報にアクセスするために System.DirectoryServicesアセンブリを参照する必要がありま す。 • ドメインやサイト関連はSystem.DirectoryServices. ActiveDirectory名前空間にそれらを表すクラスがあり、 Active Directoryの管理タスクを自動化するために使用されま す。 • Active Directory内のデータにアクセスするために使用される のは System.DirectoryServices名前空間で、オブジェクトを カプセル化する DirectoryEntryクラスやクエリを実行する DirectorySearcherクラスなどがあります。 • ADSI(Active Directory Services Interfaces)を使用してネイ ティブなオブジェクトを扱う場合は Active DS Type Library を参照する必要があります。
  4. 4. 4 主にどんなデータがあるの? 管理ツール「Active Directory ユーザとコンピュータ」で管理 する以下のオブジェクト • ユーザ • グループ • コンピュータ • 組織単位(OU) • プリンタ • 共有フォルダ
  5. 5. サンプルアプリケーションの初期画面 ドメインを取得して画面下部に 接続先を表示しています。 5
  6. 6. グループリスト画面(Windowsアプリ) 6
  7. 7. グループリスト画面(Webアプリ) 7
  8. 8. 8 どうやって接続するの? 接続先によってプロバイダが異なります。 ドメインに接続する場合 プロバイダ:LDAP(Lightweight Directory Access Protocol) 書式例:LDAP://DC=virtual,DC=proceed,DC=local ローカルに接続する場合 プロバイダ:WinNT(Windows NT) 書式例:WinNT://vpc-testclient1 これを引数にして DirectoryEntry のインスタンスを作成します。
  9. 9. 検索してグループのリストを取得する LDAPプロバイダで接続する場合 • 接続するドメインや取得したグループは DirectoryEntry オブジェクト • ユーザやグループを検索するのは DirectorySearcher オブジェクト • 複数の検索結果は SearchResultCollection として返される • SearchResult.GetDirectoryEntry メソッドで DirectoryEntry を取得 • LDAP書式のフィルター文字列(DirectorySearcher.Filter プロパティ)は 次のように指定(属性=値 をカッコで括る) • "(objectCategory=Group)" -- グループ • "(&(objectCategory=Group)(name=De*))" -- Deで始まるグループ • "(&(objectCategory=Group)(groupType<=0)" -- セキュリティ グループ • “(&(objectCategory=Volume)(!keywords=Sales)(|(uNCName=testdc*) (managedBy=CN=admin,OU=管理部,DC=test,DC=local)))” -- キーワー ドに Sales がなく、testdc 内にあるか admin が管理している共有フォ ルダ 9
  10. 10. ADSI のインターフェイス 基本インターフェイスは IADs インターフェイスで、各オブジェ クトはこのインターフェイスを継承しています。 オブジェクトとそれに対応するインターフェイス DirectoryEntry.NativeObject プロパティの値を上記インター フェイスにキャストできます。 10 ユーザ IADsUser グループ IADsGroup コンピュータ IADsComputer 組織単位(OU) IADsOU プリンタ IADsPrintQueue 共有フォルダ
  11. 11. クラスライブラリ側 名前空間直下に追加したドメイングループのスコープタイプを 表す DomainGroupScopeType 列挙体 • BuiltInLocal = -2147483643 • DomainLocal = -2147483644 • Global = -2147483646 • Universal = -2147483640 ※セキュリティグループの属性「groupType」の値と同じにな るようにしています 既存のものについてはこちらのスライドを参照してください http://www.slideshare.net/mitchin227/display-user 11
  12. 12. クラスライブラリ側に追加したクラス LocalGroup (ローカルのグループを表すクラス) プロパティ • Native (ADSI Group オブジェクトを取得) DomainGroup (ドメインのグループを表すクラス) プロパティ • Native (ADSI Group オブジェクトを取得) • Scope (グループのスコープを取得) • ScopeType (グループのスコープタイプを取得) • SecurityEnabled (セキュリティグループかどうかを取得) • Type (グループの種類を取得) メソッド • FindByName (データバインド用:グループを検索) • GetGroups (データバインド用:グループの一覧を取得) 12
  13. 13. クラスライブラリ側 DirectoryAccess クラスに追加したパブリックなメンバ GetBelongPath メソッド(所属パスを取得) ※オーバーロード GetGroups メソッド(グループを取得) GetPrimaryGroupMemberEntries メソッド(PrimaryGroupToken を持つグループをプライマリグループとしているメンバの DirectoryEntry のコレクションを取得) PathToCn メソッド(LDAPパスの名前(オブジェクト名)を取得) 13
  14. 14. フォーム側(Windowsアプリ) •ドメイングループ用とローカルグループ用の BindingSource の データソースに DomainGroup クラス、LocalGroup クラスを指 定 •詳細の各コントロールは BindingSource(クラス)のプロパ ティにバインド •グループの一覧を取得し BindingSource のデータソースに設定 •BindingSource を一覧 ListBox のデータソースに設定 •ドメインの場合は選択したグループのメンバをメンバ ListView に表示 •ローカルの場合は選択したグループのメンバ名のコレクション をメンバ ListBox のデータソースに設定 •ドメインの場合は所属するグループを所属するグループ ListView に表示 14
  15. 15. フォーム側(Webアプリ) •DomainUser クラスをビジネスオブジェクトとする ObjectDataSource を2つ用意 •グループの一覧を取得するメソッドを指定したものを一覧 ListBox のデータソースに指定 •選択したグループの名前からグループを検索するメソッドを指 定したものを詳細 FormView のデータソースに指定 •BindingSource を一覧 ListBox のデータソースに設定 •選択したグループのメンバのデータソース用のテーブルを作成 し、メンバ GridView のデータソースに設定してバインド •選択したグループの所属するグループのデータソース用のテー ブルを作成し、所属するグループ GridView のデータソースに 設定してバインド 15
  16. 16. グループ取得サンプルコード(VB) Public Shared Function GetGroups( Of T As {DirectoryObject, IGroup}) As IList(Of T) Dim groups As New List(Of T)() Using root = GetRootEntry() ’ルートのDirectoryEntryを取得 Dim filter = String.Format("(objectCategory={0})", CategoryType.Group) Using searcher As New DirectorySearcher(root, filter) Using results = searcher.FindAll() For Each res As SearchResult In results groups.Add(DirectCast(CreateInstance(res.GetDirectoryEntry()), T)) Next End Using End Using End Using Return groups End Function ※root は一般的には New DirectoryEntry(LDAPのルートパス) をセット ※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作成 16
  17. 17. グループ取得サンプルコード(C#) public static IList<T> GetGroups<T>() where T : DirectoryObject, IGroup { var grous = new List<T>(); using (var root = GetRootEntry()) { //ルートのDirectoryEntryを取得 var filter = String.Format("(objectCategory={0})", CategoryType.Group); using (var searcher = new DirectorySearcher(root, filter)) { using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { groups.Add((T)CreateInstance(res.GetDirectoryEntry())); } } } } return groups; } ※root は一般的には new DirectoryEntry(LDAPのルートパス) をセット ※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作成 17
  18. 18. ドメインのグループのスコープと種類 ドメインのグループにはスコープと種類があります。 グループのスコープ • ビルトイン ローカル • ドメイン ローカル • グローバル • ユニバーサル グループの種類 • セキュリティ • 配布 サンプルアプリでは DomainGroup クラスのコンストラクタ内で 属性「groupType」の値からスコープと種類をプロパティにセッ トしています。 18
  19. 19. メンバの表示はちょっと手間 • グループのメンバに含まれるのは ユーザ、グループ、コンピュータ、 外部のセキュリティ プリンシパル • メンバは IADsGroup.Members メソッドで取得し、ループで個々のメ ンバを処理 • ユーザやコンピュータのプライマリ グループになっていると、その ユーザやコンピュータはメンバに含まれないので、別途取得が必要 • 取得のしかたはユーザの所属 するグループの取得と同様 ※11ページのURLのスライド の17ページ参照 • 外部のセキュリティ プリン シパルは名前が SID 表記な ので、読み取り可能な名前に 変換 19
  20. 20. メンバ名の取得サンプルコード(VB) 対象グループを group As IADsGroup とすると For Each member As IADs In group.Members() Dim objectType = DirectCast([Enum].Parse(GetType(CategoryType), member.Class, True), CategoryType) 'ディレクトリ オブジェクトの種類 '外部のセキュリティプリンシパルの時 If objectType = CategoryType.ForeignSecurityPrincipal Then Dim objectSid = DirectCast(member.Get("objectSid"), Byte()) Dim sid = New SecurityIdentifier(objectSid, 0) 'SID 'アカウントに変換 Dim account = DirectCast( sid.Translate(GetType(NTAccount)), NTAccount) 'account.Value または account.ToString() でメンバ名を取得 Else '外部のセキュリティプリンシパル以外の時 'member.Get(”cn”).ToString() でメンバ名を取得 End If Next 20
  21. 21. メンバ名の取得サンプルコード(C#) 対象グループを IADsGroup group とすると foreach (IADs member in group.Members()) { var objectType = (CategoryType)Enum.Parse(typeof(CategoryType), member.Class, true); //ディレクトリ オブジェクトの種類 //外部のセキュリティプリンシパルの時 if (objectType == CategoryType.ForeignSecurityPrincipal) { var objectSid = (byte[])member.Get("objectSid"); var sid = new SecurityIdentifier(objectSid, 0); //SID //アカウントに変換 var account = (NTAccount)sid.Translate(typeof(NTAccount)); //account.Value または account.ToString() でメンバ名を取得 } else { //外部のセキュリティプリンシパル以外の時 //member.Get(”cn”).ToString() でメンバ名を取得 } } 21
  22. 22. 所属するグループの取得 • 所属するグループは属性「memberOf」で取得 • DirectoryEntry なら Properties プロパティで、IADs なら GetEx メソッドで取得(どちらも引数は ”memberOf”) • Properties プロパティの項目の型は PropertyValueCollection • GetEx メソッドの戻り値は Object 型であるが、内部的には配列が 返される(memberOf の場合は文字列の配列)ので、IEnumerable に キャストして ループで個々の要素を処理(値がない場合は例外がス ローされる) • 各要素の値はLDAPのパス形式(下記) CN=Administrators,CN=Builtin,DC=test,DC=local 参考:IADs の GetEx メソッドと Get メソッド GetEx メソッドの戻り値は内部的には配列になるが、Get メソッドの 戻り値は 複数の値の場合は配列、単一の値の場合は非配列になる 単一の値しか持たない属性(前ページの objectSid など)を取得する なら Get メソッドを使用することでループ処理が不要になる 22
  23. 23. 所属するグループの取得サンプルコード 対象グループを group(DirectoryEntry 型)とすると VB For Each groupPath As String In group.Properties.Item("memberOf") name = DirectoryAccess.PathToCn(groupPath) '名前を取得 path = DirectoryAccess.GetBelongPath(groupPath) '所属パスを取得 Next C# foreach (string groupPath in group.Properties["memberOf"]) { name = DirectoryAccess.PathToCn(groupPath); //名前を取得 path = DirectoryAccess.GetBelongPath(groupPath); //所属パスを取得 } 23
  24. 24. 詳細や関連情報はブログ等で .NETからActive Directoryにアクセス http://www.slideshare.net/mitchin227/active-directory-24695891 .NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~ http://www.slideshare.net/mitchin227/display-user ユーザやグループの検索 http://blogs.wankuma.com/mitchin/archive/2013/06/26/327958.aspx SearchResultCollectionクラス http://blogs.wankuma.com/mitchin/archive/2013/06/30/327977.aspx ネイティブ ADSI オブジェクト http://blogs.wankuma.com/mitchin/archive/2013/07/01/327981.aspx グループリスト画面、グループのスコープと種類 http://blogs.wankuma.com/mitchin/archive/2013/08/21/328072.aspx ドメインのグループ用のクラス http://blogs.wankuma.com/mitchin/archive/2013/08/24/328079.aspx http://blogs.wankuma.com/mitchin/archive/2013/08/25/328081.aspx 24

×