よくあるサンプルでは、ユーザをあらわす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. おわり
説明は以上です。 誤り等があればご指摘ください。
さんのコメント: さんのコメント: