よくあるサンプルでは、ユーザをあらわすDirectoryEntryを作成して、プロパティの memberOf を使用すれば、自身が直接所属しているグループの完全識別名を取得できますが、その場合、グループがほかのグループに属している場合に、リカーシブに処理をする必要があります。今回は2通りの方法でユーザが所属するすべてのグループを取得してみます。方法として、tokenGroups 属性値から所属しているグループの SID を取得し、そこからグループ名を取得します。
動作確認環境
- 動作環境: Windows 2003 Server (ドメイン環境)
- 開発環境: Visual Studio 2008 Professional
- .NET 3.5 SP1
.NET 2.0 以上で動作するはずです。
1. DirectorySearcher を使用してグループを取得する
LDAP のクエリを使用してグループをすべて取得する方法を掲載します。下記サンプルでは、ドメイン crm1.local ないの組織 CrmUsers 直下のユーザcrmuser03 の所属する全てのグループを列強するサンプルを掲載します。
public static void RetrieveGroupPattern1() { StringBuilder builder = new StringBuilder(); using (DirectoryEntry crmuser = GetDirectoryEntry("CN=crmuser03,OU=CrmUsers,DC=crm1,DC=local")) { crmuser.RefreshCache(new string[] { "tokenGroups" }); builder.Append("(|"); foreach (byte[] sid in crmuser.Properties["tokenGroups"]) { // tokenGroupsの値をSID文字列に変換して、フィルタ条件に設定 builder.AppendFormat("(objectSid={0})", ToObjectSidString(sid)); } builder.Append(")"); } using (DirectoryEntry searchRoot = GetDirectoryEntry("DC=crm1,DC=local")) { DirectorySearcher ds = new DirectorySearcher(searchRoot, builder.ToString()); using (SearchResultCollection searchResultCollection = ds.FindAll()) { foreach (SearchResult searchResult in searchResultCollection) { Console.WriteLine(searchResult.Properties["samAccountName"][0]); } } } } private static string ToObjectSidString(byte[] bytes) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < bytes.Length; ++i) { builder.AppendFormat(@"\{0}", bytes[i].ToString("X2")); } return builder.ToString(); } private static DirectoryEntry GetDirectoryEntry(string dn) { return new DirectoryEntry("LDAP://" + dn, null, null, AuthenticationTypes.Secure); }
tokenGroupsはconstructedな属性値のため、RefreshCacheを使用して、取得する必要があります。取得した全ての所属グループのSIDを DirectorySearcher のフィルタ条件(objectSid)にしています。
実行結果は次のようになります。
Domain Users
Users
2. IdentityReferenceCollection を使用してグループを取得する
tokenGroups 属性値の SIDから IdentityReferenceCollection.Translate メソッドを使用して System.Security.Principal.NTAccount 型 に変換してグループ名を列挙します。
public static void RetrieveGroupsPattern2() { using (DirectoryEntry crmuser = GetDirectoryEntry("CN=crmuser03,OU=CrmUsers,DC=crm1,DC=local")) { crmuser.RefreshCache(new string[] { "tokenGroups" }); IdentityReferenceCollection identityReferenceCollection = new IdentityReferenceCollection(); foreach (byte[] tokenGroup in crmuser.Properties["tokenGroups"]) { identityReferenceCollection.Add(new SecurityIdentifier(tokenGroup, 0)); } identityReferenceCollection = identityReferenceCollection.Translate(typeof(NTAccount)); foreach (NTAccount account in identityReferenceCollection) { Console.WriteLine(account.Value); } } }
実行結果は次のようになります。
BULTIN\Users
CRM1\Domain Users
3. おわり
説明は以上です。 誤り等があればご指摘ください。
さんのコメント: さんのコメント: