netからactive directoryデータにアクセス ~組織単位(ou)情報の取得と表示~

21
.NET かか Active Directory かかかかかかかか かかかかOU かかかかかかか かか かかか mitchin Microsoft MVP for Directory Services

Upload: michio-koyama

Post on 27-Jun-2015

1.312 views

Category:

Technology


1 download

DESCRIPTION

Get OrganizationalUnit(OU) objects from Active Directory and display on a windows/web form.

TRANSCRIPT

Page 1: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

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

組織単位( OU )情報を表示する

小山 三智男mitchin

Microsoft MVP for Directory Services

Page 2: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

2

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

開発環境• Domain : Windows Server 2008 、 Windows Server 2012

R2• Client : Windows 8.1 Pro 、 Windows 7 Professional SP1• IDE : Visual Studio Professional 2013• Projects : Windows Forms(.NET 4.5.1)

Web Forms(.NET 4.5.1) IE11 、 IE10Class Library(.NET 4.5.1)※ ソースコード自体は .NET 4 相当

実行環境• DC : Windows Server 2008 Standard SP2(.NET 4.5.1)• IIS : Windows 認証• Client : Windows 7 Professional SP1 、 IE10

Page 3: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

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データにアクセス ~組織単位(OU)情報の取得と表示~

4

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

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

Page 5: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

5

ADSI

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

DirectoryEntry.NativeObject プロパティの値を上記インターフェイスにキャストできます。但し IADsComputer は LDAP をサポートしていないので 実質キャストできません。

ユーザ IADsUser

グループ IADsGroup

コンピュータ IADsComputer

組織単位( OU) IADsOU

プリンタ IADsPrintQueue

共有フォルダ

Page 6: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

6

どうやって接続するの?

ドメインに接続するには LDAP を使います。プロバイダ: LDAP(Lightweight Directory Access Protocol)書式例: LDAP://DC=virtual,DC=proceed,DC=local

この LDAP の接続文字列を引数にして DirectoryEntry のインスタンスを作成します。作成した DirectoryEntry がドメインを表し、検索のルートになります。( DirectorySearcher の引数になります。)この場合、検索範囲はドメイン全体ということになります。

Page 7: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

7

検索して OU のリストを取得する

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

は次のように指定(属性 = 値 をカッコで括る)• "(objectCategory=OrganizationalUnit)" -- OU• "(&(objectCategory=OrganizationalUnit)(!location=* 本社 ))" -- 本

社以外の OU• "(&(objectCategory=OrganizationalUnit)(|(st= 東京都 )(st= 大阪

府 )))" -- 都道府県が東京か大阪の OU

Page 8: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

8

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

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

Page 9: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

9

プロパティと属性の対応

プロパティ画面の「全般」タブの項目に対応する属性です。

Page 10: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

10

組織単位リスト画面( Windows アプリ)

Page 11: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

11

組織単位リスト画面( Web アプリ)

Page 12: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

12

クラスライブラリ側に追加したクラス

OrganizationalUnit ( 組織単位を表すクラス )

プロパティ• City ( 市区町村を取得または設定 )• PostalCode ( 郵便番号を取得または設定 )• Prefecture ( 都道府県を取得または設定 )• StoredDomainObjects ( 直下のオブジェクトを取得 )• Street ( 番地を取得または設定 )

メソッド• FindByPath ( データバインド用:指定したパスの OU を検索 )• Dispose ( オーバーライド:リソースを解放 )

Page 13: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

13

フォーム側( Windows アプリ)

• BindingSource のデータソースに OrganizationalUnit クラスを指定•初期画面と同じ内容の ImageList を一覧 TreeView 及び直下のデータ表示用 ListView のイメージに設定•詳細の「データ」以外の各コントロールは BindingSource(クラス)のプロパティにバインド• OU の一覧を取得し、表示用のパスと名前でソートしたものを内部保持してそれを BindingSource のデータソースに設定•取得した OU の数を表示•一覧 TreeView に OU のノードを作成して追加•一覧から OU を選択すると、内部保持しているリストから 選択された OU を抽出し、 OUBindingSource の Position を設定•選択された OU に格納されているデータを ListView に表示

Page 14: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

14

フォーム側( Web アプリ)

• OrganizationalUnit クラスをビジネスオブジェクトとする ObjectDataSource を詳細 FormView のデータソースに指定、 SELECT 操作に FindByPath メソッドを指定し パラメータ ソースに一覧 TreeView の SelectedValue を指定• OU の一覧を取得し、表示用のパスと名前でソートしたものを内部保持してそれを BindingSource のデータソースに設定•取得した OU の数を表示• OU に格納されているデータ格納用の Dictionary を初期化して ViewState に保持•一覧 TreeView に OU のノードを作成して追加•一覧から OU を選択すると、格納されているデータから DataTable を作成してデータ表示用 GridView にバインドし Dictionary に追加(ある場合は DataTable を取り出す)

Page 15: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

15

組織単位取得サンプルコード( VB )

Public Shared Function GetOrganizationalUnits( ) As IList(Of OrganizationalUnit) Dim ous As New List(Of OrganizationalUnit)() Using root = GetRootEntry() ' ルートの DirectoryEntry を取得 Dim filter = "(objectCategory=OrganizationalUnit)" Using searcher As New DirectorySearcher(root, filter) Using results = searcher.FindAll() For Each res As SearchResult In results ous.Add(DirectCast(CreateInstance(res.GetDirectoryEntry()), OrganizationalUnit)) 'DirectoryObject を作成して追加 Next End Using End Using End Using Return ousEnd Function※root は一般的には New DirectoryEntry(LDAP のルートパス ) をセット

Page 16: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

16

組織単位取得サンプルコード( C# )

public static IList<OrganizationalUnit> GetOrganizationalUnits() { var ous = new List<OrganizationalUnit>(); using (var root = GetRootEntry()) { // ルートの DirectoryEntry を取得 var filter = "(objectCategory=OrganizationalUnit)"; using (var searcher = new DirectorySearcher(root, filter)) { using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { ous.Add((OrganizationalUnit)CreateInstance( res.GetDirectoryEntry())); //DirectoryObject を作成して追加 } } } } return ous;}※root は一般的には new DirectoryEntry(LDAP のルートパス ) をセット

Page 17: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

17

直下のデータ取得サンプルコード( VB )Friend Shared Function GetStoredDomainObjects( ou As OrganizationalUnit) As List(Of DomainObject) Dim objects As New List(Of DomainObject)() Using searcher As New DirectorySearcher(ou.Entry) searcher.SearchScope = SearchScope.OneLevel Using results = searcher.FindAll() For Each res As SearchResult In results objects.Add(DirectCast(CreateInstance(res.GetDirectoryEntry()), DomainObject)) 'DirectoryObject を作成して追加 Next End Using End Using Return objects.OrderBy(Function(o) o.Name).ToList()End Function※ 直下のデータのみ必要なので DirectorySearcher.SearchScope プロパ

ティに SearchScope.OneLevel を指定(検索ルートは対象の OU )

Page 18: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

18

直下のデータ取得サンプルコード( C# )internal static List<DomainObject> GetStoredDomainObjects(OrganizationalUnit ou) { var objects = new List<DomainObject>(); using (var searcher = new DirectorySearcher(ou.Entry)) { searcher.SearchScope = SearchScope.OneLevel; using (var results = searcher.FindAll()) { foreach (SearchResult res in results) { objects.Add((DomainObject)CreateInstance( res.GetDirectoryEntry())); //DirectoryObject を作成して追加 } } } return objects.OrderBy(o => o.Name).ToList();}※ 直下のデータのみ必要なので DirectorySearcher.SearchScope プロパ

ティに SearchScope.OneLevel を指定(検索ルートは対象の OU )

Page 19: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

19

組織単位の検索サンプルコード( VB )

<DataObjectMethod(DataObjectMethodType.Select)>Public Shared Function FindByPath(path As String) As OrganizationalUnit 'distinguishedName を生成 Dim ouNames = path.Split("/"c).Reverse() Dim sb As New StringBuilder() For Each ouName In ouNames sb.AppendFormat("OU={0},", ouName) Next For Each dc In DirectoryAccess.DomainName.Split("."c) sb.AppendFormat("DC={0},", dc) Next sb.Length -= 1 Return DirectCast(DirectoryAccess.FindDirectoryObject(sb.ToString(), CategoryType.OrganizationalUnit), OrganizationalUnit)End Function

Page 20: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

20

組織単位の検索サンプルコード( C# )

[DataObjectMethod(DataObjectMethodType.Select)]internal static OrganizationalUnit FindByPath(string path) { //distinguishedName を生成 var ouNames = path.Split('/').Reverse(); var sb = new StringBuilder(); foreach (var ouName in ouNames) { sb.AppendFormat("OU={0},", ouName); } foreach (var dc in DirectoryAccess.DomainName.Split('.')) { sb.AppendFormat("DC={0},", dc); } sb.Length--; return (OrganizationalUnit)DirectoryAccess.FindDirectoryObject( sb.ToString(), CategoryType.OrganizationalUnit);}

Page 21: NETからActive Directoryデータにアクセス ~組織単位(OU)情報の取得と表示~

21

詳細や関連情報はブログ等で

.NET から Active Directory データにアクセス ~共有フォルダの取得と表示~

http://www.slideshare.net/mitchin227/display-folder

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

Active Directory 内のオブジェクトの検索指定http://blogs.wankuma.com/mitchin/archive/2013/06/28/327969.aspx

組織単位( OU)http://blogs.wankuma.com/mitchin/archive/2014/03/01/328414.aspx

組織単位( OU )用のクラスhttp://blogs.wankuma.com/mitchin/archive/2014/03/02/328419.aspxhttp://blogs.wankuma.com/mitchin/archive/2014/03/04/328422.aspx

DirectoryAccess クラスに追加した組織単位( OU )関連のメソッドhttp://blogs.wankuma.com/mitchin/archive/2014/03/11/328434.aspx

Windows Server 2012 R2 で Active Directory 始めました。http://blogs.wankuma.com/mitchin/archive/2014/05/05/330117.aspx