web-dev-qa-db-fra.com

Vérifier si l'utilisateur actuel est administrateur

Mon application doit exécuter des scripts et je dois m'assurer que l'utilisateur qui les exécute est un administrateur ... Quelle est la meilleure façon de procéder à l'aide de C #?

69
Fliskov
using System.Security.Principal;

public static bool IsAdministrator()
{
    using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}
81
Nissim
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
27
Alex Reitbort

Vous pouvez également appeler l'API Windows pour effectuer cette opération:

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

qui vous indique de manière plus générique si l’utilisateur fonctionne sous des droits élevés.

7
Rick Strahl

Les réponses ci-dessus avec IsInRole sont en réalité correctes: il vérifie si l'utilisateur actuel dispose des privilèges d'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, deux jetons d'accès au moment de l'exécution vous sont attribués: 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. 

(à partir 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 la méthode retournera donc false. Vrai seulement lorsque le logiciel est explicitement exécuté en tant qu'administrateur.

L’autre méthode qui vérifie AD dans https://ayende.com/blog/158401/are-you-an-administrator vérifie si le nom de l’utilisateur appartient à un groupe d’administrateurs.

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)
            {
                // Even if the user is defined in the Admin group, UAC defines 2 roles: one user and one admin. 
                // IsInRole consider the current default role as user, thus will return false!
                // Will consider the admin role only if the app is explicitly run as admin!
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                isElevated = principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            else
            {
                // read all roles for the current identity name, asking ActiveDirectory
                isElevated = IsAdministratorNoCache(identity.Name);
            }
        }

        return isElevated;
    }

    /// <summary>
    /// Determines whether the specified user is an administrator.
    /// </summary>
    /// <param name="username">The user name.</param>
    /// <returns>
    ///   <c>true</c> if the specified user is an administrator; otherwise, <c>false</c>.
    /// </returns>
    /// <seealso href="https://ayende.com/blog/158401/are-you-an-administrator"/>
    private static bool IsAdministratorNoCache(string username)
    {
        PrincipalContext ctx;
        try
        {
            Domain.GetComputerDomain();
            try
            {
                ctx = new PrincipalContext(ContextType.Domain);
            }
            catch (PrincipalServerDownException)
            {
                // can't access domain, check local machine instead 
                ctx = new PrincipalContext(ContextType.Machine);
            }
        }
        catch (ActiveDirectoryObjectNotFoundException)
        {
            // not in a domain
            ctx = new PrincipalContext(ContextType.Machine);
        }
        var up = UserPrincipal.FindByIdentity(ctx, username);
        if (up != null)
        {
            PrincipalSearchResult<Principal> 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 d'un groupe d'administrateur 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 le privilège administrateur, considérez le paramètre checkCurrentRole == true. Sinon, vous obtiendrez une exception de sécurité d'ici là . Par conséquent, la logique IsInRole correcte.

6
EricBDev

Je pensais juste que j'ajouterais une autre solution; comme la IsInRole ne fonctionne pas toujours.

  • Si l'utilisateur n'est pas membre du groupe d'utilisateurs Windows spécifié dans la session en cours.
  • L'administrateur a modifié les paramètres de stratégie de groupe.
  • Le paramètre de rôle est traité comme une méthode «sensible à la casse».
  • Et si la version .NET Framework n'est pas installée sur un ordinateur XP, il ne fonctionnera pas.

En fonction de vos besoins, si vous devez prendre en charge des systèmes plus anciens. ou ne savez pas comment votre client gère physiquement votre système. C'est une solution que j'ai implémentée. pour la flexibilité et les modifications.

class Elevated_Rights
    {

        // Token Bool:
        private bool _level = false;

        #region Constructor:

        protected Elevated_Rights()
        {

            // Invoke Method On Creation:
            Elevate();

        }

        #endregion

        public void Elevate()
        {

            // Get Identity:
            WindowsIdentity user = WindowsIdentity.GetCurrent();

            // Set Principal
            WindowsPrincipal role = new WindowsPrincipal(user);

            #region Test Operating System for UAC:

            if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6)
            {

                // False:
                _level = false;

                // Todo: Exception/ Exception Log

            }

            #endregion

            else
            {

                #region Test Identity Not Null:

                if (user == null)
                {

                    // False:
                    _level = false;

                    // Todo: "Exception Log / Exception"

                }

                #endregion

                else
                {

                    #region Ensure Security Role:

                    if (!(role.IsInRole(WindowsBuiltInRole.Administrator)))
                    {

                        // False:
                        _level = false;

                        // Todo: "Exception Log / Exception"

                    }

                    else
                    {

                        // True:
                        _level = true;

                    }

                    #endregion


                } // Nested Else 'Close'

            } // Initial Else 'Close'

        } // End of Class.

Donc, le code ci-dessus a quelques constructions; il va effectivement tester pour voir si l'utilisateur est sur Vista ou supérieur. Ainsi, si un client est sur XP sans un cadre ou un cadre bêta d’il ya des années, cela vous permettra de modifier ce que vous souhaitez faire.

Ensuite, il va tester physiquement pour éviter une valeur nulle pour le compte.

Enfin, il fournira le moyen de vérifier que l'utilisateur joue bien le rôle qui convient.

Je sais que la question a été répondue; mais je pensais que ma solution serait un excellent ajout à la page pour toute autre personne cherchant Stack. Mon raisonnement derrière le constructeur protégé vous permettrait d'utiliser cette classe en tant que classe dérivée que vous pouvez contrôler l'état de l'instanciation de la classe. 

2
Greg

Je dois être sûr que l'utilisateur qui les exécute est un administrateur

Si votre application doit être exécutée avec des droits d'administrateur, il serait correct de mettre à jour son manifeste.
Définissez requestedExecutionlevel sur requireAdminstrator.

0
Qwertiy