programing

Active Directory에서 사용자 그룹을 가져오는 방법은 무엇입니까?(c#, asp.net )

minimums 2023. 6. 2. 20:18
반응형

Active Directory에서 사용자 그룹을 가져오는 방법은 무엇입니까?(c#, asp.net )

이 코드를 사용하여 현재 사용자의 그룹을 가져옵니다.그러나 사용자에게 수동으로 제공한 다음 그룹을 가져오려고 합니다.어떻게 해야 하나요?

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;
}

3 .NET 3.5 버전을 할 수 .System.DirectoryServices.AccountManagement 작업할 수 있습니다 (S.DS.AM)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개 그룹 중 2개 그룹에 대한 예외가 있었기 때문입니다.(그Translate()호출은 SID -> 이름 변환을 수행합니다.)

우선 GetAuthorizationGroups()는 훌륭한 기능이지만 다음과 같은 두 가지 단점이 있습니다.

  1. 특히 사용자와 그룹이 많은 대기업의 경우 성능이 떨어집니다.실제로 필요한 것보다 훨씬 더 많은 데이터를 가져오고 결과의 각 루프 반복에 대해 서버 호출을 수행합니다.
  2. 그룹과 사용자가 진화할 때 '언젠가' 애플리케이션이 작동을 중지할 수 있는 버그가 포함되어 있습니다.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;
}

내에모사는속가성집다니을용자든서▁▁property다▁a▁withinmemberOf여기에는 사용자가 속한 모든 그룹의 목록이 포함됩니다.

다음은 작은 코드 예제입니다.

// (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);
}
}

내 솔루션:

UserPrincipal user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain, myDomain), IdentityType.SamAccountName, myUser);
List<string> UserADGroups = new List<string>();            
foreach (GroupPrincipal group in user.GetGroups())
{
    UserADGroups.Add(group.ToString());
}

제 경우 GetGroups()를 아무런 예상 없이 계속 사용할 수 있는 유일한 방법은 AD(Active Directory)를 읽을 수 있는 권한을 가진 그룹에 사용자(USER_WITH_PERMISION)를 추가하는 것이었습니다.이 사용자와 암호를 전달하는 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 내부에서 수행할 수 있는 단계:

  1. Active Directory에 그룹을 만들고(또는 그룹을 만듭니다) 보안 탭에서 "Windows Authorization Access Group"을 추가합니다.
  2. "고급" 버튼을 클릭합니다.
  3. "Windows Authorization Access Group"을 선택하고 "View"를 클릭합니다.
  4. "TokenGroupsGlobalAndUniversal 읽기"를 선택합니다.
  5. 원하는 사용자를 찾아 첫 번째 단계에서 만든 그룹에 추가합니다.

검색할 그룹의 종류에 따라 답이 달라집니다.System.DirectoryServices.AccountManagement네임스페이스는 두 가지 그룹 검색 방법을 제공합니다.

GetGroups - 현재 주체가 멤버인 그룹을 지정하는 그룹 개체의 컬렉션을 반환합니다.

이 오버로드된 메서드는 주체가 직접 멤버인 그룹만 반환하고 재귀 검색은 수행되지 않습니다.

GetAuthorizationGroups - 이 사용자가 멤버인 모든 권한 부여 그룹을 포함하는 주 개체의 컬렉션을 반환합니다.이 함수는 Security Group인 그룹만 반환하고 배포 그룹은 반환하지 않습니다.

이 메서드는 모든 그룹을 재귀적으로 검색하고 사용자가 구성원인 그룹을 반환합니다.반환된 세트에는 시스템이 권한 부여 목적으로 사용자를 구성원으로 간주하는 추가 그룹이 포함될 수도 있습니다.

그렇게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();

이것은 나에게 효과가 있습니다.

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();
    }

번역이 로컬에서는 작동하지만 원격에서는 작동하지 않는 경우.번역(((NTAcount) 유형)

로그인한 사용자 ID를 사용하여 응용 프로그램 코드를 실행하려면 가장을 사용하도록 설정합니다.IIS를 통해 또는 web.config에 다음 요소를 추가하여 가장을 사용할 수 있습니다.

<system.web>
<identity impersonate="true"/>

가장이 활성화된 경우 사용자 계정에 있는 사용 권한을 사용하여 응용 프로그램이 실행됩니다.따라서 로그인한 사용자가 특정 네트워크 리소스에 액세스할 수 있는 경우에만 애플리케이션을 통해 해당 리소스에 액세스할 수 있습니다.

그의 부지런한 비디오에서 얻은 이 정보에 대해 PRAGIM tech에게 감사합니다.

asp.net 의 Windows 인증 Part 87:

https://www.youtube.com/watch?v=zftmaZ3ySMc

그러나 가장하면 서버에 많은 오버헤드가 발생합니다.

특정 네트워크 그룹의 사용자에게 허용하는 가장 좋은 해결책은 웹 구성에서 익명을 거부하는 것입니다.<authorization><deny users="?"/><authentication mode="Windows"/>

그리고 뒤에 있는 코드, 가급적이면 global.asax에서 HttpContext를 사용합니다.현재.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

참고: 그룹은 백슬래시로 작성해야 합니다. 즉, "도메인"더 그룹"

이것은 빠르고 더럽지만 누군가 도움이 될 수도 있습니다.시스템에 참조를 추가해야 합니다.디렉터리 서비스.이 작업에 대한 계정 관리입니다.이는 사용자 역할을 얻기 위한 것이지만 필요한 경우 다른 항목을 포함하도록 확장할 수 있습니다.

using System.DirectoryServices.AccountManagement;

PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "DaomainName");
UserPrincipal u = UserPrincipal.FindByIdentity(ctx, "Username");

List<UserRole> UserRoles = u.GetGroups().Select(x => new UserRole { Role = x.Name }).ToList();

public partial class UserRole
{
    public string Role { get; set; }
}

언급URL : https://stackoverflow.com/questions/5309988/how-to-get-the-groups-of-a-user-in-active-directory-c-asp-net

반응형