2012-03-13 2 views
4

Impersonation exampleКак проверить, не является ли пользователь с [UserName] и [Password] администратором домена [DomainName] без олицетворения?

я могу проверить, является администратором домена пользователя со следующими строками кода:

using (Impersonation im = new Impersonation(UserName, Domain, Password)) 
{ 
    System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent(); 
    bool isDomainAdmin = identity.IsDomainAdmin(Domain, UserName, Password); 
    if (!isDomainAdmin) 
    { 
     //deny access, for example 
    } 
} 

где IsDomainAdmin - это метод расширения

public static bool IsDomainAdmin(this WindowsIdentity identity, string domain, string userName, string password) 
{ 
    Domain d = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, domain, userName, password)); 

    using (DirectoryEntry de = d.GetDirectoryEntry()) 
    { 
     byte[] domainSIdArray = (byte[])de.Properties["objectSid"].Value; 
     SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0); 
     SecurityIdentifier domainAdminsSId = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, domainSId); 
     WindowsPrincipal wp = new WindowsPrincipal(identity); 
     return wp.IsInRole(domainAdminsSId); 
    } 
} 

Но, когда метод IsDomainAdmin называется, оно пытаясь записать некоторые файлы в% LOCALAPPDATA% для олицетворенного пользователя, и если программа запущена не как администратор, она выдает исключение

Не удалось загрузить файл или сборку 'System.DirectoryServices, Version = 4.0.0.0, культура = нейтральной, PublicKeyToken = b03f5f7f11d50a3a' или один из его зависимостей. Либо требуемый уровень олицетворения не был указан , либо предоставленный уровень олицетворения недействителен. (Исключение из HRESULT: 0x80070542)

+0

Полезная http://stackoverflow.com/questions/12160262/how- can-i-define-if-a-windows-identity-to-a-local-or-a-domain-use – Kiquenet

ответ

3

Вы, конечно, не нужен пароль пользователя, чтобы проверить, если пользователь является членом группы. Итак, почему бы вам просто не запросить AD прямолинейно, используя DirectoryEntry или DirectorySearcher? Если вам также необходимо проверить правильность введенного пароля, вы можете сделать это на дополнительном шаге, используя PrincipalContext.ValidateCredentials. (См. PrincipalContext.ValidateCredentials Method (String, String)).

static void Main(string[] args) { 
    string userDomain = "somedomain"; 
    string userName = "username"; 
    string password = "apassword"; 

    if (IsDomainAdmin(userDomain, userName)) { 
     string fullUserName = userDomain + @"\" + userName; 
     PrincipalContext context = new PrincipalContext(
      ContextType.Domain, userDomain); 
     if (context.ValidateCredentials(fullUserName, password)) { 
      Console.WriteLine("Success!"); 
     } 
    } 
} 

public static bool IsDomainAdmin(string domain, string userName) { 
    string adminDn = GetAdminDn(domain); 
    SearchResult result = (new DirectorySearcher(
     new DirectoryEntry("LDAP://" + domain), 
     "(&(objectCategory=user)(samAccountName=" + userName + "))", 
     new[] { "memberOf" })).FindOne(); 
    return result.Properties["memberOf"].Contains(adminDn); 
} 

public static string GetAdminDn(string domain) { 
    return (string)(new DirectorySearcher(
     new DirectoryEntry("LDAP://" + domain), 
     "(&(objectCategory=group)(cn=Domain Admins))") 
     .FindOne().Properties["distinguishedname"][0]); 
} 
+0

первая часть права - мне нужно проверить credenti пользователя БАС. Я не знаю достаточно о запросах LDAP, но если я изменю '' cn = Domain Admins ''' 'cn = Domain Users" ', я всегда получаю false, но я знаю, что пользователь с указанным именем существует. Может быть, есть некоторые ошибки в запросах? – stukselbax

+0

Пользователи AD не добавляются явным образом в группу «Пользователи домена»; это подразумевается. Таким образом, dn для группы пользователей домена не будет в списке memberOf. Попробуйте найти пользователя и перечислить элементы в 'memberOf', чтобы лучше понять. –

+0

Его работы! НО! Мне не нравится решение с жестко закодированной строкой '" Domain Admins "'. Может ли группа администраторов домена иметь другое имя в некоторой структуре AD? – stukselbax

2

Мы модифицируются @jmh_gr ответ, и это, кажется, становится независимым от имени "Domain Admins" группы.

static string BuildOctetString(SecurityIdentifier sid) 
{ 
    byte[] items = new byte[sid.BinaryLength]; 
    sid.GetBinaryForm(items, 0); 
    StringBuilder sb = new StringBuilder(); 
    foreach (byte b in items) 
    { 
     sb.Append(b.ToString("X2")); 
    } 
    return sb.ToString(); 
} 
public static bool IsDomainAdmin(string domain, string userName) 
{ 
    using (DirectoryEntry domainEntry = new DirectoryEntry(string.Format("LDAP://{0}", domain))) 
    { 
     byte[] domainSIdArray = (byte[])domainEntry.Properties["objectSid"].Value; 

     SecurityIdentifier domainSId = new SecurityIdentifier(domainSIdArray, 0); 
     SecurityIdentifier domainAdminsSId = new SecurityIdentifier(WellKnownSidType.AccountDomainAdminsSid, domainSId); 

     using (DirectoryEntry groupEntry = new DirectoryEntry(string.Format("LDAP://<SID={0}>", BuildOctetString(domainAdminsSId)))) 
     { 
      string adminDn = groupEntry.Properties["distinguishedname"].Value as string; 
      SearchResult result = (new DirectorySearcher(domainEntry, string.Format("(&(objectCategory=user)(samAccountName={0}))", userName), new[] { "memberOf" })).FindOne(); 
      return result.Properties["memberOf"].Contains(adminDn); 
     } 
    } 
} 

В любом случае, спасибо @jmh_gr за ответ.

+0

Спасибо, отлично поработал! – meilon

0

Используя этот код @lluisfranco образца

using System.DirectoryServices; 
using System.DirectoryServices.ActiveDirectory; 
using System.Net.NetworkInformation; 
using System.Security.Principal; 

namespace Alpha.Code 
{ 
    public static class SecurityExtensions 
    { 
     public static bool IsDomainAdmin (this WindowsIdentity identity) 
     { 
      Domain d = Domain.GetDomain(new 
       DirectoryContext(DirectoryContextType.Domain, getDomainName())); 
      using (DirectoryEntry de = d.GetDirectoryEntry()) 
      { 
       byte[] bdomSid = (byte[])de.Properties["objectSid"].Value; 
       string sdomainSid = sIDtoString(bdomSid); 
       WindowsPrincipal wp = new WindowsPrincipal(identity); 
       SecurityIdentifier dsid = new SecurityIdentifier(sdomainSid); 
       SecurityIdentifier dasid = new SecurityIdentifier(
        WellKnownSidType.AccountDomainAdminsSid, dsid); 
       return wp.IsInRole(dasid); 
      } 
     } 

     public static string getDomainName() 
     { 
      return IPGlobalProperties.GetIPGlobalProperties().DomainName; 
     } 

     public static string sIDtoString(byte[] sidBinary) 
     { 
      SecurityIdentifier sid = new SecurityIdentifier(sidBinary, 0); 
      return sid.ToString(); 
     } 
    } 
} 

Использование:

if (WindowsIdentity.GetCurrent().IsDomainAdmin()) 
{ 
    //Actions to do if user is domain admin 
} 

Источник:
http://geeks.ms/blogs/lfranco/archive/2009/11/25/how-to-191-como-saber-si-el-usuario-actual-es-administrador-del-dominio.aspx

+0

Это то же самое решение, что и в вопросе. – stukselbax

+0

@stukselbax Какое окончательное решение: http://stackoverflow.com/a/9684475/206730 или http://stackoverflow.com/a/9698448/206730? – Kiquenet

+0

Мы использовали последний, потому что он не зависел от имени, но основная идея возникла из первого ответа. Оба ответа действительны. – stukselbax

Смежные вопросы