.NET 3.5 から ユーザ管理用のクラスをまとめた名前空間 AccountManagement が追加されています。PrincipalContext や UserPrincipal クラスを使用すると、タイプセーフな方法で、ユーザの名前やログイン日付による検索、ユーザの情報やロック状態の取得、解除等様々なユーザ管理テスクを間単に行えるようになります。AccountManagement名前空間のクラスを使用するには、System.DirectoryServices.AccountManagement.dllへの参照を追加するのを忘れないでください。同様にSystem.DirectoryServices 名前空間のクラスはSystem.DirectoryServices.dllの参照が必要です。
AccountManagement 名前空間の説明のリンクを掲載しておきます。
System.DirectoryServices.AccountManagement 名前空間の概要
http://msdn.microsoft.com/ja-jp/library/bb384379.aspx
1. LDAPの接続
PrincipalContext を使用すると簡単に、LDAPに接続する準備を行えます。PrincipalContext を作成するサンプルの一つを掲載します。詳細な説明はMSDNを参照してください。サンプルでは、test.localドメインのコンテナUsersを処理対象のルートパスとして、初期化しています。
PrincipalContext ctxt = new PrincipalContext(ContextType.Domain, "test.local", "OU=Users,DC=test,DC=local");
System.DirectoryServices 名前空間で該当する処理はActiveDirectoryにバインドして、DirectoryEntryを作成処理が該当します。サンプルでは、実行ユーザの視覚情報を使用して、ADにバインドするサンプルを掲載しています。
string connectionString = "LDAP://test.local/OU=Users,DC=test,DC=local"; DirectoryEntry entry= new DirectoryEntry(connectionString, null, null, AuthenticationTypes.Secure); object o = entry.NativeObject;
1.1 ユーザの検索
ユーザの検索はFindByメソッドを使用して行えます。
UserPrincipal user = UserPrincipal.FindByIdentity(ctxt, IdentityType.SamAccountName, "user1");
同じことをSystem.DirectorySevices のクラスを使用すると次のようになります。result は、SearchResult型のインスタンスで、result.GetDirectoryEntry メソッドを使用して、検査結果のディレクトリエントリを取得できます。
DirectoryEntry searchRoot = GetSearchRoot(); // 検索のルートパスを表すDirectoryEntry using (DirectorySearcher ds = new DirectorySearcher(searchRoot)) { string filter = "(&(objectClass=user)(sAMAccountName=user1))"; ds.Filter = filter; ds.SizeLimit = 1; result = ds.FindOne(); }
1.2 ユーザの検証
user1という名前のユーザのパスワードがあっているかを検証します。検証処理の注意点ですが、パスワードの有効期限が切れている、ロックアウトされている、次回パスワード変更が必要の場合、いずれも検証が失敗します。ChangePasswordの場合は、ロックアウト以外では処理を行うことができます。
if (ctxt.ValidateCredentials("user1", "password")) { MessageBox.Show("OK!!"); } else { MessageBox.Show("DAME"); }
同様の処理を既存のDirectoryEntry クラスで行おうとする場合、次のようになります。指定されたユーザ、パスワード情報でDirectoryEntryにバインドできるかで検証します。
string userId = "user1"; string currentPassword = "passowrd"; string connectionString = "LDAP://test.local/OU=Users,DC=test,DC=local"; DirectoryEntry entry= new DirectoryEntry(connectionString, userName, password, AuthenticationTypes.Secure); object o = entry.NativeObject;
同様のことをDirectoryEntryを使用すると次のようにInvokeを呼び出します。
DirectoryEntry entry = GetChangeUser(); // 変更対象ユーザ取得 entry.Invoke("ChangePassword", oldPassword, newPassword);
1.3 パスワードの変更
パスワードの変更は、UserPrincipalのChangePasswordメソッドを使用します。
user.ChangePassword("oldpassword11", "newpassword12");
DirectoryEntry を使用する場合は、ChangePasswordをInvokeします。アカウントが変更できないに設定されていたり、ロックアウトされている以外はパスワードを変更できます。パスワードの有効期限切れや初回パスワード変更が必要な場合も旧パスワードがあっていればパスワードを変更できます。
entry.Invoke("ChangePassword", oldPassword, newPassword);
1.4 パスワードの設定
user.SetPassword("newpassword33");
DirectoryEntry を使用する場合は、ChangePasswordと同様にInvokeを呼び出します。ただし、旧パスワードは必要ありませんが、ChangePasswordと異なり、Administratorのような高い権限が必要となります。
entry.Invoke("ChangePassword", oldPassword, newPassword);
1.5 ユーザのロック解除
UserPrincipal user = UserPrincipal.FindByIdentity(ctxt, IdentityType.SamAccountName, "lockeduser"); if (user.IsAccountLockedOut()) { user.UnlockAccount(); }
DirectoryEntry を使用す場合は、InvokeGet,InvokeSet を使用しまます。サンプルではロックされているかを調べる例を刑咲いています。
// ロックされているかを調べるユーザのDirectoryEntry取得 DirectoryEntry user = GetLockCheckUser(); bool locked = (bool) user.InvokeGet("IsAccountLocked")
2. まとめ
今回の説明は以上です。誤りなどがありましたら、ご指摘ください。
AccountManagement 名前空間にはユーザ管理タスクを簡単にするクラスが追加されています。UserPrincipal クラスは紹介していること意外でも様々な機能があります。MSDNのドキュメントを参照していただければと思います。
さんのコメント: さんのコメント: