109 votes

Vérifiez si l'utilisateur actuel est administrateur

Mon application a besoin d'exécuter quelques scripts, et je dois m'assurer que l'utilisateur qui les exécute est un administrateur... Quel est le meilleur moyen de le faire en utilisant C# ?

117voto

Nissim Points 2174
en utilisant System.Security.Principal;

public static bool IsAdministrator()
{
    en utilisant (WindowsIdentity identity = WindowsIdentity.GetCurrent())
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}

7 votes

Juste une note que ce qui précède ne fonctionnera pas si le Contrôle de compte d'utilisateur (UAC) est activé dans Vista ou Win7 ; vous devrez afficher une boîte de confirmation UAC et élever les permissions dans ce cas.

0 votes

1 votes

@AnkurTripathi Es-tu...?

37voto

Alex Reitbort Points 9120
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);

44 votes

@Nissm: Vous avez tous les deux répondu simultanément, ou assez près pour que 5 minutes après le fait que vous soyez tous les deux mentionnés comme ayant posté "Il y a 5 minutes". Il n'y a aucune raison pour vous d'attaquer Alex; nous ne sommes pas ici pour gagner en réputation, nous sommes ici pour aider.

0 votes

23voto

Rick Strahl Points 4166

Vous pouvez également appeler l'API Windows pour faire cela:

[DllImport("shell32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsUserAnAdmin();

ce qui vous indique de manière plus générique si l'utilisateur est en cours d'exécution avec des droits élevés.

6 votes

Il s'agit de loin de la méthode la plus rapide pour faire cela, 25 fois plus rapide.

16voto

EricBDev Points 339

Les réponses ci-dessus avec IsInRole sont en fait correctes : cela vérifie si l'utilisateur actuel a le privilège administrateur. Cependant,

À partir de Windows Vista, le Contrôle de compte d'utilisateur (UAC) détermine les privilèges d'un utilisateur. Si vous êtes membre du groupe Administrateurs intégrés, vous disposez de deux jetons d'accès en cours d'exécution : un jeton d'accès utilisateur standard et un jeton d'accès administrateur. Par défaut, vous êtes dans le rôle d'utilisateur standard.

(de MSDN, par exemple https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogpermission(v=vs.110).aspx)

Ainsi, IsInRole considérera par défaut le privilège de l'utilisateur, et donc la méthode renverra false. Seulement vrai lorsque le logiciel est explicitement exécuté en tant qu'administrateur.

L'autre méthode vérifiant dans l'AD sur https://ayende.com/blog/158401/are-you-an-administrator vérifiera si le nom d'utilisateur est dans un groupe d'administration.

Ma méthode complète combinant les deux est donc :

    public static bool IsCurrentUserAdmin(bool checkCurrentRole = true)
    {
        bool isElevated = false;

        using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
        {
            if (checkCurrentRole)
            {
                // Même si l'utilisateur est défini dans le groupe Admin, UAC définit 2 rôles : un utilisateur et un administrateur. 
                // IsInRole considère le rôle par défaut actuel comme utilisateur, donc retournera false !
                // Considérera le rôle administrateur uniquement si l'application est explicitement exécutée en tant qu'administrateur !
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                isElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            else
            {
                // lire tous les rôles pour le nom d'identité actuel, en interrogeant ActiveDirectory
                isElevated = IsAdministratorNoCache(identity.Name);
            }
        }

        return isElevated;
    }

    /// 
    /// Détermine si l'utilisateur spécifié est un administrateur.
    /// 
    /// Le nom d'utilisateur.
    /// 
    ///   true si l'utilisateur spécifié est un administrateur ; sinon, false.
    /// 
    /// 
    private static bool IsAdministratorNoCache(string username)
    {
        PrincipalContext ctx;
        try
        {
            Domain.GetComputerDomain();
            try
            {
                ctx = new PrincipalContext(ContextType.Domain);
            }
            catch (PrincipalServerDownException)
            {
                // impossible d'accéder au domaine, vérifier la machine locale à la place 
                ctx = new PrincipalContext(ContextType.Machine);
            }
        }
        catch (ActiveDirectoryObjectNotFoundException)
        {
            // pas dans un domaine
            ctx = new PrincipalContext(ContextType.Machine);
        }
        var up = UserPrincipal.FindByIdentity(ctx, username);
        if (up != null)
        {
            PrincipalSearchResult authGroups = up.GetAuthorizationGroups();
            return authGroups.Any(principal =>
                                  principal.Sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) ||
                                  principal.Sid.IsWellKnown(WellKnownSidType.AccountDomainAdminsSid) ||
                                  principal.Sid.IsWellKnown(WellKnownSidType.AccountAdministratorSid) ||
                                  principal.Sid.IsWellKnown(WellKnownSidType.AccountEnterpriseAdminsSid));
        }
        return false;
    }

Pour un utilisateur dans un groupe d'administration sans privilège élevé (UAC activé), cette méthode IsCurrentUserAdmin() renvoie !checkCurrentRole : true si checkCurrentRole==false, mais false si checkCurrentRole==true

Si vous exécutez du code qui REQUIERT un privilège administratif, envisagez de définir checkCurrentRole==true. Sinon, vous obtiendrez une exception de sécurité à ce moment-là. Par conséquent, la logique correcte de IsInRole.

0 votes

C'est vraiment bien mais semble toujours incomplet. Et si le domaine avait un groupe global qui était finalement membre du groupe des administrateurs locaux? Il ne semble pas que cela corresponde. Je ne peux pas tester cela aujourd'hui car je suis chez moi mais peut-être que je vais essayer au travail quand je reviendrai au bureau.

0 votes

Cela convient, mais comme le dit l'auteur du blog, c'est trop lent.

8voto

David Ching Points 1364

Comme d'autres ici, mon programme ne s'exécute pas en mode élevé, donc ce code renvoie false si UAC est activé :

private bool IsCurrentUserAnAdmin()
{
    var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}

La réponse de @EricBDev avec IsAdministratorNoCache renvoie true si mon programme ne s'exécute pas en mode élevé et que l'utilisateur est un Administrateur. Cependant, comme l'auteur du blog le dit, c'est très lent.

Voici ma solution ; elle émule IsAdministratorNoCache mais est rapide :

private bool IsCurrentUserInAdminGroup()
{
    // https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/security-identifiers-in-windows
    // S-1-5-32-544
    // Un groupe intégré. Après l'installation initiale du système d'exploitation,
    // le seul membre du groupe est le compte Administrateur.
    // Lorsqu'un ordinateur rejoint un domaine, le groupe Domain Admins est ajouté au
    // groupe Administrateurs. Lorsqu'un serveur devient un contrôleur de domaine,
    // le groupe Enterprise Admins est également ajouté au groupe Administrateurs.
    var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
    var claims = principal.Claims;
    return (claims.FirstOrDefault(c => c.Value == "S-1-5-32-544") != null);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X