Pytanie Pobierz nETBIOSName z obiektu UserPrincipal


Używam części System.DirectoryServices.AccountManagement biblioteki .Net do interfejsu ActiveDirectory.

Po wywołaniu GetMembers () na obiekcie GroupPrincipal i przefiltrowaniu wyników, mam teraz kolekcję obiektów UserPrincipal

GroupPrincipal myGroup;  // population of this object omitted here 

foreach (UserPrincipal user in myGroup.GetMembers(false).OfType<UserPrincipal>())
{
    Console.WriteLine(user.SamAccountName);
}

Powyższy przykładowy kod wypisze nazwy użytkownika takie jak "TestUser1". Muszę je porównać do listy pochodzącej z innej aplikacji w formacie "DOMAIN \ TestUser1".

Jak uzyskać część "DOMAIN" z obiektu UserPrincipal?

Nie mogę po prostu dołączyć znanej nazwy domeny, ponieważ dotyczy to wielu domen i muszę odróżnić DOMAIN1 \ TestUser1 i DOMAIN2 \ TestUser2.


12
2017-11-26 10:54


pochodzenie


@marc_s Nazwa UserPrincipleName zawiera imię i nazwisko w formacie name@fulness.qualified.domain.name - nie widzę sposobu łatwego przekonwertowania tego na format DOMAIN \ user (szczególnie, że domeny, których dotyczy ta sprawa, są znaną listą - każde środowisko produkcyjne będzie inna lista domen niż moje środowisko programistyczne) - Grhm
Możesz także użyć msDS-PrincipalName właściwość opisana tutaj stackoverflow.com/questions/10702188 - Greg Bray
Albo użyj user.Sid.Translate(typeof(System.Security.Principal.NTAccount)).ToString() aby uzyskać domenę \ nazwa_użytkownika każdego członka grupy. Widzieć stackoverflow.com/questions/6759463 - Greg Bray
@GregBray msDs-Principalname nie istniał w Win2003 dla systemów AD LDS (patrz msdn.microsoft.com/en-us/library/cc221208.aspx) i AD DS może zawierają nazwę NETBIOS (patrz msdn.microsoft.com/en-us/library/cc223404.aspx). Nie mam już dostępu do domen, w których początkowo miałem ten problem, aby sprawdzić - ale Twoja sugestia może być przydatna dla tych, którzy śledzą ... - Grhm


Odpowiedzi:


Masz dwie możliwości, o których mogę pomyśleć.

  1. Parsuj, lub weź wszystko, co jest, prawo name@fully.qualified.domain.name;
  2. Użyj System.DirectoryServices przestrzeń nazw.

Nie wiem UserPrincipalI ja też nie GroupPrincipal. Z drugiej strony, wiem o działającym sposobie osiągania tego, co chcesz.

[TestCase("LDAP://fully.qualified.domain.name", "TestUser1")] 
public void GetNetBiosName(string ldapUrl, string login)
    string netBiosName = null;
    string foundLogin = null;

    using (DirectoryEntry root = new DirectoryEntry(ldapUrl))
        Using (DirectorySearcher searcher = new DirectorySearcher(root) {
            searcher.SearchScope = SearchScope.Subtree;
            searcher.PropertiesToLoad.Add("sAMAccountName");
            searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);

            SearchResult result = null;

            try {
                result = searcher.FindOne();

                if (result == null) 
                    if (string.Equals(login, result.GetDirectoryEntry().Properties("sAMAccountName").Value)) 
                        foundLogin = result.GetDirectoryEntry().Properties("sAMAccountName").Value
            } finally {
                searcher.Dispose();
                root.Dispose();
                if (result != null) result = null;
            }
        }

    if (!string.IsNullOrEmpty(foundLogin)) 
        using (DirectoryEntry root = new DirectoryEntry(ldapUrl.Insert(7, "CN=Partitions,CN=Configuration,DC=").Replace(".", ",DC=")) 
            Using DirectorySearcher searcher = new DirectorySearcher(root)
                searcher.Filter = "nETBIOSName=*";
                searcher.PropertiesToLoad.Add("cn");

                SearchResultCollection results = null;

                try {
                    results = searcher.FindAll();

                    if (results != null && results.Count > 0 && results[0] != null) {
                        ResultPropertyValueCollection values = results[0].Properties("cn");
                        netBiosName = rpvc[0].ToString();
                } finally {
                    searcher.Dispose();
                    root.Dispose();

                    if (results != null) {
                        results.Dispose();
                        results = null;
                    }
                }
            }

    Assert.AreEqual("INTRA\TESTUSER1", string.Concat(netBiosName, "\", foundLogin).ToUpperInvariant())
}

Inne powiązane informacje lub łącza dostępne w tym pytaniu dotyczącym SO.
C # Active Directory: Uzyskaj nazwę domeny użytkownika?
Jak znaleźć nazwę NetBIOS domeny


4
2017-11-26 14:35



Wygląda dobrze, ale nie działa. Wynik.GetDirectoryEntry () nie ma właściwości "nETBIOSName" - zawsze ma wartość null. (Plus musiałem użyć właściwości ["nETBIOSName"]. Wartość i mój obiekt wyniku nie ma Dispose () - przy użyciu .Net4, jeśli to robi różnicę) - Grhm
@Grmh: Edytowałem swoją odpowiedź. Proszę spojrzeć na to i powiedzieć mi, czy to działa. Zamknąłem go w NUnit TestCase dla łatwości testowania. - Will Marcouiller
@Will: Nie wydaje mi się, że w mojej domenie znajduje się "CN = Partitions, CN = Configuration". Moja domena najwyraźniej jest domeną podrzędną, a rodzic ma sekcję CN = copnfiguration. Będę musiał zbadać .... - Grhm
Jeśli wyślę zapytanie do domeny nadrzędnej, otrzymają dwa wyniki. results [0] .Properties ["cn"] [0] nadaje domenom nadrzędnym nazwę NetBIOS, a wyniki [1] .Properties ["cn"] [0] nadaje domenom podrzędnym nazwę NetBIOS. Daje to listę możliwych nazw NETBIOS. Sądzę, że będę musiał sprawdzić każdą kombinację netbiosname \ loginname, aby sprawdzić, czy zwraca prawidłowego użytkownika i czy pasuje do oryginalnego użytkownika. Wydaje się jednak kręty. :( - Grhm
@Grhm: Zgoda, jest kręta. Myślę, że najprostszym sposobem byłoby zajęcie odpowiedniej części @ podpisać na login@fully.qualified.domain.name i sparsuj je, aby utworzyć fully.qualified.domain.name\login. Czy to działa najlepiej dla Ciebie? - Will Marcouiller


Użyj biblioteki COM ActiveDs, ma wbudowane tłumaczenie nazw, które działa i nie ma żadnych założeń (jak inne odpowiedzi tutaj).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ActiveDs;

namespace Foo.Repository.AdUserProfile
{
    public class ADUserProfileValueTranslate
    {
        public static string ConvertUserPrincipalNameToNetBiosName(string userPrincipleName)
        {
            NameTranslate nameTranslate = new NameTranslate();
            nameTranslate.Set((int)ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_USER_PRINCIPAL_NAME, userPrincipleName);
            return nameTranslate.Get((int) ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_NT4);
        }
    }
}

2
2018-06-05 14:27





Czy próbowałeś przekazać w pełni kwalifikowaną nazwę domeny do tej innej aplikacji? Większość Windows API nie będzie narzekać, jeśli to zrobisz fully_qualified_domain\USER.


0
2017-11-26 14:15



Niestety druga aplikacja przechowuje nazwy użytkowników w bazie danych i oczekuje, że nazwa użytkownika będzie unikatowa. Łączy się również z wieloma innymi aplikacjami, do których nie mam dostępu. - Grhm


Możesz wyszukać możliwe domeny w właściwości user.DistinguishedName. Użytkownik w domenie 1 powinien zawierać ciąg "DC = DOMAIN1". Zdecydowanie nie powinien zawierać ciągu "DC = DOMAIN2".


0
2017-08-20 16:21



Niekoniecznie. Miałem domenę, która była user1@dev.project.local lub PROJECTDEV \ User1 User.DistinguishedName zakończona z DC = dev, DC = project, DC = local nie zawiera DC = PROJECTDEV - Grhm
Ah - thx za korektę. Myślałem, że nazwa wyróżniająca się w pewnym sensie jest polem obliczeniowym - i jest spójna w moim środowisku. - GC.


Jak wspomniano w jednym z komentarzy do pytania, uważam, że jest to dobra odpowiedź na nowsze czasy:

 user.Sid.Translate(typeof(System.Security.Principal.NTAccount)).ToString()

0
2017-07-27 01:24