このコードを使用して、現在のユーザーのグループを取得します。しかし、私は手動でユーザーを与えてから、彼のグループを取得したいと思います。これどうやってするの?
using System.Security.Principal;
public ArrayList Groups()
{
ArrayList groups = new ArrayList();
foreach (IdentityReference group in System.Web.HttpContext.Current.Request.LogonUserIdentity.Groups)
{
groups.Add(group.Translate(typeof(NTAccount)).ToString());
}
return groups;
}
.NET 3.5以降を使用している場合は、新しいSystem.DirectoryServices.AccountManagement
(S.DS.AM)名前空間を使用できます。これにより、以前よりもずっと簡単になります。
ここですべてを読んでください: 。NET Framework 3.5 でのディレクトリセキュリティプリンシパルの管理
更新:古いMSDNマガジンの記事は残念ながらもうオンラインではありません-2008年1月のMSDNのCHMをダウンロードする必要があります Microsoftのmagazine で記事を読んでください。
基本的に、「プリンシパルコンテキスト」(通常はドメイン)、ユーザープリンシパルが必要であり、そのグループを非常に簡単に取得できます。
public List<GroupPrincipal> GetGroups(string userName)
{
List<GroupPrincipal> result = new List<GroupPrincipal>();
// establish domain context
PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain);
// find your user
UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, userName);
// if found - grab its groups
if(user != null)
{
PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
// iterate over all groups
foreach(Principal p in groups)
{
// make sure to add only group principals
if(p is GroupPrincipal)
{
result.Add((GroupPrincipal)p);
}
}
}
return result;
}
そしてそれだけです!これで、ユーザーが属する許可グループの結果(リスト)が得られました-それらを反復処理し、名前または必要なものを印刷します。
Update:UserPrincipal
オブジェクトに表示されない特定のプロパティにアクセスするには、基になるDirectoryEntry
を掘り下げる必要があります。
public string GetDepartment(Principal principal)
{
string result = string.Empty;
DirectoryEntry de = (principal.GetUnderlyingObject() as DirectoryEntry);
if (de != null)
{
if (de.Properties.Contains("department"))
{
result = de.Properties["department"][0].ToString();
}
}
return result;
}
更新#2:は、これら2つのコードスニペットをまとめるのにそれほど難しくないように思われます....
public string GetDepartment(string username)
{
string result = string.Empty;
// if you do repeated domain access, you might want to do this *once* outside this method,
// and pass it in as a second parameter!
PrincipalContext yourDomain = new PrincipalContext(ContextType.Domain);
// find the user
UserPrincipal user = UserPrincipal.FindByIdentity(yourDomain, username);
// if user is found
if(user != null)
{
// get DirectoryEntry underlying it
DirectoryEntry de = (user.GetUnderlyingObject() as DirectoryEntry);
if (de != null)
{
if (de.Properties.Contains("department"))
{
result = de.Properties["department"][0].ToString();
}
}
}
return result;
}
GetAuthorizationGroups()
は、ネストされたグループを見つけません。特定のユーザーが(ネストされたグループを含む)メンバーであるすべてのグループを実際に取得するには、これを試してください:
using System.Security.Principal
private List<string> GetGroups(string userName)
{
List<string> result = new List<string>();
WindowsIdentity wi = new WindowsIdentity(userName);
foreach (IdentityReference group in wi.Groups)
{
try
{
result.Add(group.Translate(typeof(NTAccount)).ToString());
}
catch (Exception ex) { }
}
result.Sort();
return result;
}
try/catch
を使用するのは、一部のSIDが使用できなくなったため、非常に大きなADで200グループ中2グループの例外が発生したためです。 (Translate()
呼び出しはSID->名前変換を行います。)
まず、GetAuthorizationGroups()は優れた機能ですが、残念ながら2つの欠点があります。
そのため、GetAuthorizationGroups()をより優れたパフォーマンスとエラーセーフで置き換える小さな関数を作成しました。インデックス付きフィールドを使用するクエリでは、LDAP呼び出しは1回のみです。グループ名( "cn"プロパティ)以外のプロパティが必要な場合は、簡単に拡張できます。
// Usage: GetAdGroupsForUser2("domain\user") or GetAdGroupsForUser2("user","domain")
public static List<string> GetAdGroupsForUser2(string userName, string domainName = null)
{
var result = new List<string>();
if (userName.Contains('\\') || userName.Contains('/'))
{
domainName = userName.Split(new char[] { '\\', '/' })[0];
userName = userName.Split(new char[] { '\\', '/' })[1];
}
using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domainName))
using (UserPrincipal user = UserPrincipal.FindByIdentity(domainContext, userName))
using (var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domainContext.Name)))
{
searcher.Filter = String.Format("(&(objectCategory=group)(member={0}))", user.DistinguishedName);
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("cn");
foreach (SearchResult entry in searcher.FindAll())
if (entry.Properties.Contains("cn"))
result.Add(entry.Properties["cn"][0].ToString());
}
return result;
}
AD内では、すべてのユーザーにmemberOf
プロパティがあります。これには、彼が属するすべてのグループのリストが含まれます。
以下に小さなコード例を示します。
// (replace "part_of_user_name" with some partial user name existing in your AD)
var userNameContains = "part_of_user_name";
var identity = WindowsIdentity.GetCurrent().User;
var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();
var allSearcher = allDomains.Select(domain =>
{
var searcher = new DirectorySearcher(new DirectoryEntry("LDAP://" + domain.Name));
// Apply some filter to focus on only some specfic objects
searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", userNameContains);
return searcher;
});
var directoryEntriesFound = allSearcher
.SelectMany(searcher => searcher.FindAll()
.Cast<SearchResult>()
.Select(result => result.GetDirectoryEntry()));
var memberOf = directoryEntriesFound.Select(entry =>
{
using (entry)
{
return new
{
Name = entry.Name,
GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString())
};
}
});
foreach (var item in memberOf)
{
Debug.Print("Name = " + item.Name);
Debug.Print("Member of:");
foreach (var groupName in item.GroupName)
{
Debug.Print(" " + groupName);
}
Debug.Print(String.Empty);
}
}
私の場合、私は無理なくGetGroups()を使い続けることができる唯一の方法は、AD(Active Directory)を読み取る権限を持つグループにユーザー(USER_WITH_PERMISSION)を追加することでした。このユーザーとパスワードを渡すPrincipalContextを構築することは非常に重要です。
var pc = new PrincipalContext(ContextType.Domain, domain, "USER_WITH_PERMISSION", "PASS");
var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName);
var groups = user.GetGroups();
Active Directory内で実行して動作させる手順:
- Active Directoryにグループを作成(または取得)し、[セキュリティ]タブの下に[Windows Authorization Access Group]を追加します
- 「詳細設定」ボタンをクリックします
- 「Windows Authorization Access Group」を選択し、「View」をクリックします
- 「TokenGroupsGlobalAndUniversalの読み取り」をチェックします
- 目的のユーザーを見つけて、最初のステップで作成(取得)したグループに追加します
これは私のために働く
public string[] GetGroupNames(string domainName, string userName)
{
List<string> result = new List<string>();
using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName))
{
using (PrincipalSearchResult<Principal> src = UserPrincipal.FindByIdentity(principalContext, userName).GetGroups())
{
src.ToList().ForEach(sr => result.Add(sr.SamAccountName));
}
}
return result.ToArray();
}
Translateがローカルでは機能するがリモートでは機能しない場合e.i group。Translate(typeof(NTAccount)
LOGGED IN USER IDを使用してアプリケーションコードを実行する場合は、偽装を有効にします。偽装はIISを介して、またはweb.configに次の要素を追加することで有効にできます。
<system.web>
<identity impersonate="true"/>
偽装が有効になっている場合、アプリケーションはユーザーアカウントで見つかった権限を使用して実行されます。そのため、ログインしているユーザーが特定のネットワークリソースにアクセスできる場合にのみ、アプリケーションを介してそのリソースにアクセスできます。
彼の勤勉なビデオからのこの情報については、PRAGIM techに感謝します
Asp.netパート87のWindows認証:
https://www.youtube.com/watch?v=zftmaZ3ySMc
しかし、なりすましはサーバーに多くのオーバーヘッドを作成します
特定のネットワークグループのユーザーを許可する最適なソリューションは、Web構成で匿名を拒否することです<authorization><deny users="?"/><authentication mode="Windows"/>
コードビハインド、できればglobal.asaxで、HttpContext.Current.User.IsInRoleを使用します。
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
If HttpContext.Current.User.IsInRole("TheDomain\TheGroup") Then
//code to do when user is in group
End If
注:グループはバックスラッシュ\ i.e. "TheDomain\TheGroup"で記述する必要があります
答えは、取得するグループの種類によって異なります。 System.DirectoryServices.AccountManagement
名前空間は、2つのグループ取得方法を提供します。
GetGroups -現在のプリンシパルがメンバーになっているグループを指定するグループオブジェクトのコレクションを返します。
このオーバーロードされたメソッドは、プリンシパルが直接メンバーであるグループのみを返します。再帰的な検索は実行されません。
GetAuthorizationGroups -このユーザーがメンバーとなっているすべての承認グループを含むプリンシパルオブジェクトのコレクションを返します。この関数は、セキュリティグループであるグループのみを返します。配布グループは返されません。
このメソッドは、すべてのグループを再帰的に検索し、ユーザーがメンバーになっているグループを返します。返されるセットには、システムがユーザーを承認の目的でメンバーと見なす追加のグループも含まれる場合があります。
したがって、GetGroups
は、ユーザーがdirectメンバーであるallグループを取得し、GetAuthorizationGroups
はすべてを取得しますauthorizationユーザーがdirectまたはindirectメンバーであるグループ。
名前の付け方にも関わらず、一方は他方のサブセットではありません。 GetGroups
によって返されないグループと、GetAuthorizationGroups
によって返されないグループが存在する場合があります。
以下に使用例を示します。
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "MyDomain", "OU=AllUsers,DC=MyDomain,DC=Local");
UserPrincipal inputUser = new UserPrincipal(domainContext);
inputUser.SamAccountName = "bsmith";
PrincipalSearcher adSearcher = new PrincipalSearcher(inputUser);
inputUser = (UserPrincipal)adSearcher.FindAll().ElementAt(0);
var userGroups = inputUser.GetGroups();