2012-03-23 3 views
13

Chcę móc uzyskać identyfikator użytkownika w usłudze Active Directory przy użyciu wyświetlanej nazwy tego użytkownika. Wyświetlana nazwa jest otrzymywany z bazy danych, a został zapisany podczas sesji, która użytkownika za pomocą następującego kodu, aby uzyskać nazwę wyświetlaną:Jak uzyskać nazwę użytkownika w usłudze Active Directory z wyświetlanej nazwy w języku C#?

using System.DirectoryServices.AccountManagement; 

    private string GetDisplayName() 
    { 
     // set up domain context 
     PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 

     // find currently logged in user 
     UserPrincipal user = UserPrincipal.Current; 

     return user.DisplayName; 
    } 

Tym razem chciałbym mieć to metoda o nazwie GetUserIdFromDisplayName() że zwraca Nazwa logowania usługi Active Directory. Jakieś pomysły?

+1

Nie zweryfikowałem tego, więc nie jestem w 100% pewny, ale myślę, że chcesz mieć właściwość "SamAccountName". – CodingGorilla

+0

Czy myślisz, że to jest możliwe? Wątpię, aby wyświetlane nazwy użytkowników były unikalne. Prawdopodobnie doprowadziłoby to do wyników wielorzędowych. –

+0

Prawda. Teraz rozważam użycie GUID zamiast używając poniższej odpowiedzi. –

Odpowiedz

28

Uważam, że można to zrobić o wiele łatwiej niż za pomocą odpowiedzi Davida, używając wbudowanej funkcjonalności przestrzeni nazw System.DirectoryServices.AccountManagement (S.DS.AM).

Zasadniczo, można określić kontekst domeny i łatwo znaleźć użytkowników i/lub grupy w AD:

using System.DirectoryServices.AccountManagement; 

private string GetUserIdFromDisplayName(string displayName) 
{ 
    // set up domain context 
    using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
    { 
     // find user by display name 
     UserPrincipal user = UserPrincipal.FindByIdentity(ctx, displayName); 

     // 
     if (user != null) 
     { 
      return user.SamAccountName; 
      // or maybe you need user.UserPrincipalName; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
} 

Nie widzę żadnej potrzeby, aby przejść do leżącej DirectoryEntry obiektu, naprawdę - chyba nikt z właściwości tego, czego szukasz, są naprawdę prawdziwe.

PS: Jeżeli wyszukiwanie według nazwy wyświetlacza nie powinny działać (nie mam pod ręką AD przetestować go teraz) - zawsze można również użyć PrincipalSearcher znaleźć użytkownika:

using System.DirectoryServices.AccountManagement; 

private string GetUserIdFromDisplayName(string displayName) 
{ 
    // set up domain context 
    using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
    { 
     // define a "query-by-example" principal - here, we search for a UserPrincipal 
     // and with the display name passed in 
     UserPrincipal qbeUser = new UserPrincipal(ctx); 
     qbeUser.DisplayName = displayName; 

     // create your principal searcher passing in the QBE principal  
     PrincipalSearcher srch = new PrincipalSearcher(qbeUser); 

     // find match - if exists 
     UserPrincipal user = srch.FindOne() as UserPrincipal; 

     if (user != null) 
     { 
      return user.SamAccountName; 
      // or maybe you need user.UserPrincipalName; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
} 
+2

+1, łatwiejsze i szybsze, znajduje także wpisy DOMAIN \ USERID oraz – smirkingman

+0

Udało mi się znaleźć użytkowników według domeny DOMAIN \ USERNAME za pomocą 'UserPrincipal.FindByIdentity (ctx, IdentityTypes.SamAccountName, nazwa użytkownika), więc zakładam, że chcesz zwróć 'user.SamAccountName' podobnie jak stany kodu. – Pakman

7

UserPrincipal ma metodę GetUnderlyingObject(), która zwróci wartość DirectoryEntry.

Get DirectoryEntry z Zleceniodawca:

private DirectoryEntry GetDirectoryEntryFromUserPrincipal(Principal user) 
{ 
    return (DirectoryEntry)user.GetUnderlyingObject(); 
} 

Get DirectoryEntry z domeny oraz numer konta:

private DirectoryEntry GetDirectoryEntryFromDomainAndUsername(string domainName, string userName) 
{ 
    // Get the sid from the NT account name 
    var sid = (SecurityIdentifier) new NTAccount(domainName, accountName) 
        .Translate(typeof(SecurityIdentifier)); 

    // Get the directory entry for the LDAP service account 
    var serviceEntry = new DirectoryEntry("LDAP://{address}", "serviceUsername", "servicePassword"); 

    var mySearcher = new DirectorySearcher(serviceEntry) 
     { 
      Filter = string.Format("(&(ObjectSid={0}))", sid.Value) 
     }; 

    return mySearcher.FindOne().GetDirectoryEntry(); 
} 

Gdy masz DirectoryEntry użyć właściwości Guid aby uzyskać wpis na Object-Guid

private Guid GetObjectGuidFromDirectoryEntry(DirectoryEntry entry) 
{ 
    // return the Guid this is the Object-Guid (ignore NativeGuid) 
    return entry.Guid; 
} 

Aby śledzić konto użytkownika w aplikacji na koncie katalogowym: zawsze używaj Object-Guid jako "Ta wartość jest ustawiana, gdy obiekt jest tworzony i nie można go zmienić."
Nazwy kont NT i SAM mogą ulec zmianie, jeśli użytkownik zmieni domeny lub, częściej, zmieni swoją nazwę (małżeństwo, zmiana nazwy prawnej itp.) I nie powinien być używany do śledzenia użytkownika.

Aby uzyskać nazwę konta NT (domena \ nazwa_użytkownika):

private string GetNTAccountNameFromDirectoryEntry(DirectoryEntry entry) 
{ 
    PropertyValueCollection propertyValueCollection = entry.Properties["objectsid"]; 

    SecurityIdentifier sid = new SecurityIdentifier((byte[]) propertyValueCollection[0], 0); 

    NTAccount ntAccount = (NTAccount)sid.Translate(typeof (NTAccount)); 

    return account.ToString(); 
} 

Aby uzyskać SAM-Account-Name (nazwa użytkownika @ domena):

private string GetSAMAccountFromDirectoryEntry(DirectoryEntry entry) 
{ 
    return entry.Properties["Name"].Value; 
} 

i oto exhaustive list wszystkich atrybutów Active Directory. Użyj "Ldap-Display-Name", aby uzyskać wartość od Properties np. Properties["Ldap-Display-Name"]

Display-Name (FirstName MI LastName) może się przydać.

+0

Dzięki! Wtedy przypuszczam, że musisz uzyskać obiekty 'UserPrincipal' z grupy AD, wykonując coś takiego: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/ecb16a63-6619-4c68-a77c-8bb2682fc1be –

+0

To by działało. Widziałem, że używasz 'UserPrincipal.Current' w swoim pytaniu. Działa to, jeśli aplikacja internetowa jest hostowana w domenie przy użyciu "Windows Security" lub jest natywną aplikacją działającą w sesji użytkownika. Jeśli możesz tylko zapytać o AD, pobierz wpis bezpośrednio, filtrując według nazwy konta SAM. – David

+0

Dodano GetDirectoryEntryFromDomainAndUsername. To może wymagać trochę ulepszenia, ponieważ nie jestem w środowisku, w którym mogę przetestować to wszystko na serwerze AD. – David