netからactive directoryデータにアクセス ~ユーザ情報の取得と表示~

Post on 18-Dec-2014

3.021 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

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

ユーザ情報の取得と表示

小山 三智男mitchin

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 認証

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

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

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

5

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

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

6

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

7

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

8

どうやって接続するの?

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

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

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

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 枚以上印刷できるプリンタ

10

ADSI のインターフェイス

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

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

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

ユーザ IADsUser

グループ IADsGroup

コンピュータ IADsComputer

組織単位( OU) IADsOU

プリンタ IADsPrintQueue

共有フォルダ

11

クラスライブラリ側

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

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

12

クラスライブラリ側

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

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

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

13

クラスライブラリ側

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

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

14

フォーム側

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

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

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

のデータソースに設定

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

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

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

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

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

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 を作成しま

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 を作成しま

17

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

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

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

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

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 メソッドの呼出し)でプロパティをロードしています。

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 メソッドの呼出し)で

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

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

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

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

top related