이 코드를 사용하여 현재 사용자의 그룹을 가져옵니다. 하지만 수동으로 사용자에게 부여한 다음 그룹을 가져오고 싶습니다. 어떻게 할 수 있습니까?
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 잡지 기사가 더 이상 온라인 상태가 아닙니다. 안타깝게도 Microsoft에서 2008 년 1 월 MSDN 잡지 CHM 을 다운로드하고 그 기사를 읽어야합니다.
기본적으로 “주요 컨텍스트”(일반적으로 도메인), 사용자 주체가 있어야하며 그룹을 매우 쉽게 얻을 수 있습니다.
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;
}
그게 전부입니다! 이제 사용자가 속한 권한 그룹의 결과 (목록)가 생겼습니다.이를 반복하고 이름을 인쇄하거나 필요한 모든 작업을 수행합니다.
업데이트 :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 : 이 두 코드 조각을 합치는 것이 너무 어렵지 않을 것 같습니다 ….하지만 괜찮습니다.
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 개 그룹이 밖으로 몇 가지 예외가 없었기 때문에. ( Translate()
호출은 SID-> 이름 변환을 수행합니다.)
답변
우선 GetAuthorizationGroups ()는 훌륭한 함수이지만 불행히도 두 가지 단점이 있습니다.
- 특히 사용자와 그룹이 많은 대기업에서는 성능이 좋지 않습니다. 실제로 필요한 것보다 훨씬 많은 데이터를 가져오고 결과의 각 루프 반복에 대해 서버 호출을 수행합니다.
- 여기에는 그룹과 사용자가 진화 할 때 애플리케이션이 ‘언젠가’작동을 멈출 수있는 버그가 포함되어 있습니다. Microsoft는 문제를 인식했으며 일부 SID와 관련이 있습니다. 표시되는 오류는 “그룹을 열거하는 동안 오류가 발생했습니다.”입니다.
따라서 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 인증 액세스 그룹”을 추가합니다.
- “고급”버튼을 클릭하십시오
- “Windows 인증 액세스 그룹”을 선택하고 “보기”를 클릭하십시오.
- “읽기 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();
}
답변
대답은 검색하려는 그룹의 종류에 따라 다릅니다. System.DirectoryServices.AccountManagement
네임 스페이스는 두 그룹 검색 방법을 제공한다 :
GetGroups- 현재 보안 주체가 구성원 인 그룹을 지정하는 그룹 개체 컬렉션을 반환합니다.
이 오버로드 된 메서드는 보안 주체가 직접 구성원 인 그룹 만 반환합니다. 재귀 검색이 수행되지 않습니다.
GetAuthorizationGroups- 이 사용자가 구성원 인 모든 권한 부여 그룹을 포함하는 주체 개체의 컬렉션을 반환합니다. 이 함수는 보안 그룹 인 그룹 만 반환합니다. 메일 그룹은 반환되지 않습니다.
이 메서드는 모든 그룹을 재귀 적으로 검색하고 사용자가 구성원 인 그룹을 반환합니다. 반환 된 집합에는 시스템이 권한 부여 목적으로 사용자를 구성원으로 간주하는 추가 그룹이 포함될 수도 있습니다.
그래서 GetGroups
얻는 모든 사용자가 어떤 그룹 의 직접 멤버, 그리고 GetAuthorizationGroups
모든 가져 인증 사용자가 어떤 그룹에 직접 또는 간접 멤버.
이름이 지정되는 방식에도 불구하고 하나는 다른 하나의 하위 집합이 아닙니다. 에 의해 반환 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();