web-dev-qa-db-fra.com

Comment obtenir un nom d'utilisateur dans Active Directory à partir d'un nom d'affichage en C #?

Je veux pouvoir obtenir l'ID utilisateur d'un utilisateur dans Active Directory en utilisant le nom d'affichage de cet utilisateur. Le nom d'affichage est obtenu à partir d'une base de données et a été stocké pendant la session de cet utilisateur à l'aide du code suivant pour obtenir le nom d'affichage:

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

Cette fois-ci, j'aimerais avoir une méthode nommée GetUserIdFromDisplayName() qui renvoie le nom de connexion Active Directory. Des idées?

16
JF Beaulieu

Je pense que vous pouvez le faire beaucoup plus facilement qu'avec la réponse de David en utilisant la fonctionnalité intégrée du System.DirectoryServices.AccountManagement (S.DS.AM) espace de noms.

Fondamentalement, vous pouvez définir un contexte de domaine et trouver facilement des utilisateurs et/ou des groupes dans 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;
        }
    }
}

Je ne vois aucun besoin d'aller à l'objet DirectoryEntry sous-jacent, vraiment - à moins qu'aucune des propriétés de UserPrincipal ne soit vraiment ce que vous recherchez.

PS: si la recherche par nom d'affichage ne fonctionne pas (je n'ai pas de AD à portée de main pour le tester en ce moment) - vous pouvez toujours utiliser le PrincipalSearcher pour trouver votre utilisateur:

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

UserPrincipal a une méthode GetUnderlyingObject() qui retournera le DirectoryEntry.

Récupérer DirectoryEntry du Principal:

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

Obtenez DirectoryEntry à partir du nom de domaine et du compte:

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

Une fois que vous avez DirectoryEntry utilisez la propriété Guid pour obtenir l'entrée Object-Guid

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

Pour suivre un compte d'utilisateur dans l'application par rapport à un compte d'annuaire: utilisez toujours l'Object-Guid comme "Cette valeur est définie lorsque l'objet est créé et ne peut pas être modifiée."
Les noms de compte NT et SAM peuvent changer si l'utilisateur change de domaine ou, plus communément, change de nom (mariage, changement de nom légal, etc.) et ne doivent pas être utilisés pour suivre un utilisateur.

Pour obtenir le nom du compte NT (domaine\nom d'utilisateur):

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

Pour obtenir le nom de compte SAM (nom d'utilisateur @ domaine):

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

Et voici la liste exhaustive de tous les attributs Active Directory. Utilisez le "Ldap-Display-Name" lorsque vous obtenez la valeur de Properties
par exemple. Properties["Ldap-Display-Name"]

Display-Name (FirstName MI LastName) pourrait être utile.

8
David