22
.NET かか Active Directory かかかかかかかか かかかかかかかかかかか かか かかか mitchin

NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

.NET から Active Directory データにアクセス

ユーザ情報の取得と表示

小山 三智男mitchin

Page 2: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

2

サンプルアプリケーション

開発環境• OS : Windows7(x64)• IDE : Visual Studio 2010 SP1• アプリ: Windows フォーム (.NET 4 Client Profile)

Web フォーム (.NET 4)クラスライブラリ (.NET 4 Client Profile)

実行環境• 単一ドメイン、単一サイト、単一サブネット• サーバ: Windows Server 2008 Standard SP1 (.NET 4)• クライアント: Windows XP SP3 (.NET 4 Client Profile)• IIS : Windows 認証

Page 3: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

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を参照する必要があります。

Page 4: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

4

主にどんなデータがあるの?

管理ツール「 Active Directory ユーザとコンピュータ」で管理する以下のオブジェクト• ユーザ• グループ• コンピュータ• 組織単位( OU)• プリンタ• 共有フォルダ

Page 5: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

5

サンプルアプリケーションの初期画面

ドメインを取得して画面下部に接続先を表示しています。

Page 6: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

6

ユーザリスト画面( Windows アプリ)

Page 7: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

7

ユーザリスト画面( Web アプリ)

Page 8: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

8

どうやって接続するの?

接続先によってプロバイダが異なります。

ドメインに接続する場合プロバイダ: LDAP(Lightweight Directory Access Protocol)書式例: LDAP://DC=virtual,DC=proceed,DC=local

ローカルに接続する場合プロバイダ: WinNT(Windows NT)書式例: WinNT://vpc-testclient1

Page 9: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

9

検索してユーザのリストを取得する

LDAP プロバイダで接続する場合• 接続するドメインや取得したユーザは DirectoryEntry オブジェクト• ユーザやグループを検索するのは DirectorySearcher オブジェクト• 複数の検索結果は SearchResultCollection として返される• SearchResult.GetDirectoryEntry メソッドで DirectoryEntry を取得• LDAP 書式のフィルター文字列( DirectorySearcher.Filter プロパティ)

は次のように指定(属性 = 値 をカッコで括る)• "(objectCategory=User)" -- ユーザ• "(&(objectCategory=Group)(name=De*))" -- De で始まるグループ• "(&(objectCategory=OrganizationalUnit)(name= 一課 )" -- 一課の

OU• "(&(objectCategory=PrintQueue)(!location= 本社 ) (|

(printColor=True)(printPagesPerMinute>=30)))" -- 本社以外でカラーか 1 分間に 30 枚以上印刷できるプリンタ

Page 10: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

10

ADSI のインターフェイス

基本インターフェイスは IADs インターフェイスで、各オブジェクトはこのインターフェイスを継承しています。

オブジェクトとそれに対応するインターフェイス

DirectoryEntry.NativeObject プロパティの値を上記インターフェイスにキャストできます。

ユーザ IADsUser

グループ IADsGroup

コンピュータ IADsComputer

組織単位( OU) IADsOU

プリンタ IADsPrintQueue

共有フォルダ

Page 11: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

11

クラスライブラリ側

ディレクトリ オブジェクトの種類を表す CategoryType 列挙体• User• Group• Computer• OrganizationalUnit• PrintQueue• Volume• ForeignSecurityPrincipal

※ 名前は検索時に指定する文字列と同じになるようにしています

Page 12: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

12

クラスライブラリ側

インターフェイスIDirectory(Directory オブジェクトのプロパティを定義 )IDomain( ドメインの Directory オブジェクトのプロパティを定義 )IUser(User オブジェクトの共通プロパティを定義 )IGroup(Group オブジェクトの共通プロパティを定義 )

クラスDirectoryObject(Directory オブジェクトを表す抽象基本クラス )DomainObject( ドメインの Directory オブジェクトを表す抽象基本クラ

ス )LocalUser( ローカルのユーザを表すクラス )DomainUser( ドメインのユーザを表すクラス )

Page 13: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

13

クラスライブラリ側

DirectoryAccess クラスに追加したパブリックなメンバGroupTokens プロパティ ( グループの PrimaryGroupToken/ 名前 のリス

ト )DisposeItems メソッド ( 使用されているリソースを解放 )FindDirectoryObject メソッド (Directory オブジェクトを検索 )GetBelongGroups メソッド ( 所属するグループを取得 )GetBelongPath メソッド ( 所属パスを取得 )GetUsers メソッド ( ユーザを取得 )

Page 14: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

14

フォーム側

Windows アプリの場合• ドメインユーザ用とローカルユーザ用の BindingSource のデータソース

に DomainUser クラス、 LocalUser クラスを指定• 詳細の各コントロールは BindingSource (クラス)のプロパティにバイ

ンド• ユーザの一覧を取得し BindingSource のデータソースに設定• BindingSource を一覧 ListBox のデータソースに設定• 選択したユーザの所属するグループを取得し 所属するグループ ListBox

のデータソースに設定

Web アプリの場合• DomainUser クラスをビジネスオブジェクトとする ObjectDataSource

を 3 つ用意• ユーザの一覧を取得するメソッドを指定したものを一覧 ListBox のデータ

ソースに指定• 選択したユーザの名前からユーザを検索するメソッドを指定したものを詳

細 FormView のデータソースに指定• 選択したユーザの所属するグループを取得するメソッドを指定したものを

 所属するグループ ListBox のデータソースに指定

Page 15: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

15

ユーザ取得サンプルコード( VB )

Public Shared Function GetUsers( Of T As {DirectoryObject, IUser}) As IList(Of T) Dim users As New List(Of T)() Using root = GetRootEntry() ’ ルートの DirectoryEntry を取得 Dim filter = String.Format("(objectCategory={0})", CategoryType.User) Using searcher As New DirectorySearcher(root, filter) Using results = searcher.FindAll() For Each res As SearchResult In results users.Add(DirectCast(CreateInstance(res.GetDirectoryEntry()), T)) Next End Using End Using End Using Return usersEnd Function

※root は一般的には New DirectoryEntry(LDAP のルートパス ) をセットします※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作成しま

Page 16: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

16

ユーザ取得サンプルコード( C# )

public static IList<T> GetUsers<T>() where T : DirectoryObject, IUser { var users = new List<T>(); using (var root = GetRootEntry()) { // ルートの DirectoryEntry を取得 var filter = String.Format("(objectCategory={0})", CategoryType.User); using (var searcher = new DirectorySearcher(root, filter)) { using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { users.Add((T)CreateInstance(res.GetDirectoryEntry())); } } } } return users;}

※ root は一般的には new DirectoryEntry(LDAP のルートパス ) をセットします※CreateInstance メソッドは DirectoryEntry から DirectoryObject を作成しま

Page 17: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

17

所属するグループの取得はちょっと手間

• ユーザの所属するグループは IADsUser.Groups メソッドで取得• ただし、プライマリグループは含まれないので、別途取得する必要がある• そのためにはグループの primaryGroupToken が必要• primaryGroupToken はプロパティ( DirectoryEntry.Properties )にな

いので、ディレクトリストアからロードする必要がある• グループの primaryGroupToken =

ユーザの primaryGroupID なら、そのグループがユーザのプライマリグループ

Page 18: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

18

primaryGroupToken の取得と保持( VB )Private Shared Sub LoadGroupTokens(searcher As DirectorySearcher) searcher.Filter = String.Format( "(objectCategory={0})", CategoryType.Group) Using results = searcher.FindAll() For Each res As SearchResult In results Dim entry = res.GetDirectoryEntry() entry.Invoke("GetInfoEx", New Object() {"primaryGroupToken"}, 0) Dim token = Convert.ToInt32( entry.Properties.Item("primaryGroupToken").Value) GroupTokens.Add(token, entry.Properties.Item("cn").Value.ToString()) Next End UsingEnd Sub

DirectoryEntry.Invoke メソッド( IADs.GetInfoEx メソッドの呼出し)でプロパティをロードしています。

Page 19: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

19

primaryGroupToken の取得と保持( C# )Private static void LoadGroupTokens(DirectorySearcher searcher) { searcher.Filter = String.Format( "(objectCategory={0})", CategoryType.Group); using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { var entry = res.GetDirectoryEntry(); entry.Invoke("GetInfoEx", new object[] { "primaryGroupToken" }, 0); var token = Convert.ToInt32( entry.Properties["primaryGroupToken"].Value); GroupTokens.Add(token, entry.Properties["cn"].Value.ToString()) } }}

DirectoryEntry.Invoke メソッド( IADs.GetInfoEx メソッドの呼出し)で

プロパティをロードしています。

Page 20: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

20

所属するグループの取得( VB )

Public Shared Function GetBelongGroups( user As IUser) As ReadOnlyCollection(Of String)

Dim groups As New List(Of String)()

’ 所属するグループ数分 ( プライマリグループ以外 ) For Each group As IADs In user.Native.Groups() groups.Add(group.Get("cn").ToString()) Next

If TypeOf user Is DomainUser Then ’ ドメインユーザの時 Dim primaryGroupId = DirectCast(user,

DomainUser).PrimaryGroupId groups.Add(GroupTokens.Item(primaryGroupId)) End If groups.Sort() Return groups.AsReadOnly()End Sub

Page 21: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

21

所属するグループの取得( C# )

public static ReadOnlyCollection<string> GetBelongGroups(IUser user) {

var groups = new List<string>();

// 所属するグループ数分 ( プライマリグループ以外 ) foreach (IADs group in user.Native.Groups()) { groups.Add(group.Get("cn").ToString()); }

if (user is DomainUser) { // ドメインユーザの時 var primaryGroupId = ((DomainUser)user).PrimaryGroupId; groups.Add(GroupTokens[primaryGroupId]); } groups.Sort(); return groups.AsReadOnly();}

Page 22: NETからActive Directoryデータにアクセス ~ユーザ情報の取得と表示~

22

詳細は・・・

ブログにも書いてます。

ユーザやグループの検索http://blogs.wankuma.com/mitchin/archive/2013/06/26/327958.aspx

Active Directory 内のオブジェクトの検索指定http://blogs.wankuma.com/mitchin/archive/2013/06/28/327969.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/07/11/327999.aspx

ドメインユーザの画面への表示( Web アプリ)http://blogs.wankuma.com/mitchin/archive/2013/07/25/328019.aspx