简体   繁体   中英

How can I get DOMAIN\USER from an AD DirectoryEntry?

How can I get the Windows user and domain from an Active Directory DirectoryEntry (SchemaClassName="user") object?

The user name is in the sAMAccountName property but where can I look up the domain name?

(I can't assume a fixed domain name because the users are from various subdomains.)

This assumes that results is a SearchResultCollection obtained from a DirectorySearcher, but you should be able to get the objectsid from a DirectoryEntry directly.

SearchResult result = results[0];
var propertyValues = result.Properties["objectsid"];
var objectsid = (byte[])propertyValues[0];

var sid = new SecurityIdentifier(objectsid, 0);

var account = sid.Translate(typeof(NTAccount));
account.ToString(); // This give the DOMAIN\User format for the account

To get the DirectoryEntry domain name you can use recursion on directoryEntry.Parent . And then if directoryEntry.SchemaClassName == "domainDNS" you can get the domain name like this:

directoryEntry.Properties["Name"].Value

You won't find what you're looking for in the DirectoryEntry, unfortunately.

You have the sAMAccountName which typically is something like myuser (without the domain). You have the distinguishedName which is something like LDAP://cn=joe myuser,cn=Users,dc=yourCompany,dc=com . You also have a userPrincipalName but that's usually a name in the format of joeUser@mycompany.com .

But you won't find any attribute that has the domain\\MyUser in it, unfortunately. You'll have to put that together from your information about the domain name, and the sAMAccountName of the DirectoryEntry.

For more information and some excellent Excel sheets on all the LDAP and WinNT properties in System.DirectoryServices, check out the Hilltop Lab website by ADSI MVP Richard Mueller.

Marc

public static string GetDomainNameUserNameFromUPN(string strUPN)
{

    try
    {
        WindowsIdentity wi = new WindowsIdentity(strUPN);
        WindowsPrincipal wp = new WindowsPrincipal(wi);

       return wp.Identity.Name;



    }
    catch (Exception ex)
    {

    }

    return "";
}

I found a partitions container in CN=Partitions,CN=Configuration that contains all domains.

When you match the user to the partion you can read the real domain name from the nETBIOSName+"\\"+sAMAccountName property.

If you are using the System.DirectoryServices libraries, you should have a SearchResultsCollection from a DirectorySearcher.

Within each SearchResult's Properties collection, there is a "distinguishedname" property. That will contain all the DC parts that make up the domain your directory entry belongs to.

I wrote this pieces of code for my own usage (in VB.net, easy translation) :

 <System.Runtime.CompilerServices.Extension()>
Public Function GetDomainFQDN(ByVal Entry As DirectoryServices.DirectoryEntry) As String

    Try

        While Entry.SchemaClassName <> "domainDNS"
            Entry = Entry.Parent
        End While

        Dim DN As String = Entry.Properties("DistinguishedName").Value
        Return DN.Replace("DC=", "").Replace(",", ".")

    Catch ex As Exception
        Debug.WriteLine(ex.ToString)
        Return String.Empty
    End Try

End Function

<System.Runtime.CompilerServices.Extension()>
Public Function GetDomainNetbiosName(ByVal Entry As DirectoryServices.DirectoryEntry) As String

    Try

        While Entry.SchemaClassName <> "domainDNS"
            Entry = Entry.Parent
        End While

        Return Entry.Properties("Name").Value

    Catch ex As Exception
        Debug.WriteLine(ex.ToString)
        Return String.Empty
    End Try

End Function

I'm extending a previous answer by @laktak to provide the details of what he meant.

There is a partitions container in CN=Partitions,CN=Configuration that contains all domains which gives you the cn which is the Netbios domain name and the nCName property that contains the distinguishedName prefix a user will have if they are in this domain.

So start by searching ldap for (objectClass=*) in CN=Partitions,CN=Configuration and store the ( cn , nCName ) pairs of each result to a map.

Next you query ldap using (sAMAccountName=USERIDHERE) and get the distinguishedName from the user. Now go through the ( cn , nCName ) pairs and find the nCName that prefixes the distinguishedName from the user, and the corresponding cn is your desired Domain name.

I feel obligated to add my answer which was inspired from Nicholas DiPiazza's answer here. Hope this PowerShell code helps someone!

$hash = @{} //this contains the map of CN and nCNAME
$Filter = '(nETBIOSName=*)'
$RootOU = "CN=Partitions,CN=Configuration,DC=DOMAIN,DC=LOCAL" //Change this to your org's domain
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.SearchScope = "subtree"
$Searcher.Filter = $Filter
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($RootOU)")
$Searcher.FindAll()|sort | foreach { $hash[($_.Properties.ncname).Trim()] = ($_.Properties.cn).Trim() }
$hash.GetEnumerator() | sort -Property Value

If the user details are available in $userDetails , then the you can get the correct domain with this:

$hash[[regex]::Match($userDetails.DistinguishedName, 'DC=.*').Value]

and the final username would look like this:

$hash[[regex]::Match($userDetails.DistinguishedName, 'DC=.*').Value] + "\" + $userDetails.SamAccountName

1) You can get the userPrincipalName from the DirectoryEntry.

2) Then, split the UPN up between the Username and Domain Name.

3) Then call GetNetBIOSName() on it.

      public static DirectoryEntry GetDirectoryObject(string strPath)
        {
            if (strPath == "")
            {
                strPath = ConfigurationManager.AppSettings["LDAPPath"]; //YOUR DEFAULT LDAP PATH ie. LDAP://YourDomainServer
            }

            string username = ConfigurationManager.AppSettings["LDAPAccount"];
            string password = ConfigurationManager.AppSettings["LDAPPassword"];
                //You can encrypt and decrypt your password settings in web.config, but for the sake of simplicity, I've excluded the encryption code from this listing.

}
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write("user: " + username + ", LDAPAccount: "+ ConfigurationManager.AppSettings["LDAPAccount"] + ".<br /> "+ ex.Message +"<br />");

                if (HttpContext.Current.User.Identity != null)
                {

                    HttpContext.Current.Response.Write("HttpContext.Current.User.Identity: " + HttpContext.Current.User.Identity.Name + ", " + HttpContext.Current.User.Identity.IsAuthenticated.ToString() + "<br />");

                    HttpContext.Current.Response.Write("Windows Identity: " + WindowsIdentity.GetCurrent().Name + ", " + HttpContext.Current.User.Identity.IsAuthenticated.ToString());


                }
                else
                {
                    HttpContext.Current.Response.Write("User.Identity is null.");
                }

                HttpContext.Current.Response.End();


            }




            DirectoryEntry oDE = new DirectoryEntry(strPath, username, password, AuthenticationTypes.Secure);
            return oDE;
        }




 public static string GetNetBIOSName(string DomainName)
 {



     string netBIOSName = "";
     DirectoryEntry rootDSE =GetDirectoryObject(
         "LDAP://"+DomainName+"/rootDSE");

     string domain = (string)rootDSE.Properties[
         "defaultNamingContext"][0];

      //   netBIOSName += "Naming Context: " + domain + "<br />";

    if (!String.IsNullOrEmpty(domain))
     {

          //This code assumes you have a directory entry at the /CN=Partitions, CN=Configuration
          //It will not work if you do not have this entry.

         DirectoryEntry parts = GetDirectoryObject(
             "LDAP://"+DomainName+"/CN=Partitions, CN=Configuration," + domain);

            foreach (DirectoryEntry part in parts.Children)
         {


             if ((string)part.Properties[
                 "nCName"][0] == domain)
             {
                 netBIOSName +=  (string)part.Properties[
                     "NetBIOSName"][0];
                 break;
             }
         }


     } 
        return netBIOSName;
 }


    public static string GetDomainUsernameFromUPN(string strUPN)
{
string DomainName;
string UserName;
  if (strUPN.Contains("@"))
        {
            string[] ud = strUPN.Split('@');
            strUPN= ud[0];
            DomainName = ud[1];

            DomainName=LDAPToolKit.GetNetBIOSName(DomainName);

            UserName= DomainName + "\\" + strUPN;
        }
        else
        {
            UserName= strUPN;
        }


    return UserName;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM