Compruebe si el usuario actual es administrador

82

Mi aplicación necesita ejecutar algunos scripts y debo estar seguro de que el usuario que los ejecuta sea un administrador ... ¿Cuál es la mejor manera de hacer esto usando C #?

Fliskov
fuente

Respuestas:

96
using System.Security.Principal;

public static bool IsAdministrator()
{
    using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}
Nissim
fuente
6
Solo tenga en cuenta que lo anterior no funcionará si UAC está habilitado en Vista o Win7; Deberá abrir un cuadro de confirmación de UAC y elevar los permisos en ese caso.
MisterZimbu
1
@AnkurTripathi ¿Eres ...?
Nissim
5
Ese código no funcionará a menos que ejecute la aplicación como administrador.
AH.
35
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
Alex Reitbort
fuente
39
@Nissm: Ambos respondieron simultáneamente, o lo suficientemente cerca como para 5 minutos después del hecho de que ambos figuraron como haber publicado "hace 5 minutos". No hay ninguna razón para que ataque a Alex; no estamos aquí para ganar reputación, estamos aquí para ayudar.
Randolpho
16

También puede llamar a la API de Windows para hacer esto:

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

que le dice de manera más genérica si el usuario se está ejecutando con derechos elevados.

Rick Strahl
fuente
2
Esto es por un factor de 25 el método más rápido para hacer esto
Tobias Brohl
14

Las respuestas anteriores con IsInRole son realmente correctas: comprueba si el usuario actual tiene privilegios de administrador. Sin embargo,

A partir de Windows Vista, el Control de cuentas de usuario (UAC) determina los privilegios de un usuario. Si es miembro del grupo de administradores integrados, se le asignan dos tokens de acceso en tiempo de ejecución: un token de acceso de usuario estándar y un token de acceso de administrador. De forma predeterminada, tiene el rol de usuario estándar.

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

Por lo tanto, IsInRole considerará por defecto el privilegio del usuario y, por lo tanto, el método devolverá falso. Solo es cierto cuando el software se ejecuta explícitamente como administrador.

El otro método de verificación de AD en https://ayende.com/blog/158401/are-you-an-administrator verificará si el nombre de usuario está en un grupo de administradores.

Mi método completo combinando ambos es así:

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

Para un usuario en un grupo de administración sin privilegios elevados (UAC habilitado), este método IsCurrentUserAdmin () return! CheckCurrentRole: true si checkCurrentRole == false, pero falso si checkCurrentRole == true

Si ejecuta código que REQUIERE privilegios de administrador, considere checkCurrentRole == true. De lo contrario, obtendrá una excepción de seguridad para entonces. Por lo tanto, la lógica IsInRole correcta .

EricBDev
fuente
Esto es realmente bueno, pero aún parece incompleto. ¿Qué pasa si el dominio tiene un grupo global que, en última instancia, es miembro del grupo de administradores locales? No parece que eso coincida. No puedo probar esto hoy porque estoy en casa, pero tal vez jugaré con él en el trabajo cuando vuelva a la oficina.
Christopher Painter
2

Solo pensé en agregar otra solución; ya IsInRoleque no siempre funciona.

  • Si el usuario no es miembro del grupo de usuarios de Windows especificado en la sesión actual.
  • El administrador ha realizado cambios en la configuración de la política de grupo.
  • El parámetro de función se trata como un método "sensible a mayúsculas y minúsculas".
  • Y si una máquina XP no tiene instalada la versión de .NET Framework, no funcionará.

Dependiendo de sus necesidades si necesita admitir sistemas más antiguos; o no está seguro de cómo su cliente está administrando físicamente su sistema. Esta es una solución que implementé; para flexibilidad y alteraciones.

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.

Entonces, el código anterior tiene algunas construcciones; en realidad, probará para ver si el usuario está en Vista o superior. De esa manera, si un cliente está en XP sin un marco o marco beta de hace años, le permitirá modificar lo que le gustaría hacer.

Luego, probará físicamente para evitar un valor nulo para la cuenta.

Luego, por último, proporcionará la verificación para verificar que el usuario esté realmente en el rol adecuado.

Sé que la pregunta ha sido respondida; pero pensé que mi solución sería una gran adición a la página para cualquier otra persona que esté buscando en Stack. Mi razonamiento detrás del Constructor protegido le permitiría usar esta clase como una Clase derivada en la que podría controlar el estado en el que se crea una instancia de la clase.

Greg
fuente
0

Debo estar seguro de que el usuario que los ejecuta es un administrador.

Si su aplicación debe ejecutarse con derechos de administrador, sería correcto actualizar su manifiesto.
Establecer requestedExecutionlevelen requireAdminstrator.

Qwertiy
fuente
0

Así es como termino ... estoy forzando a que mi aplicación se ejecute como modo administrador. Para hacer esto

1- Agregue <ApplicationManifest>app.manifest</ApplicationManifest>a su csprojarchivo.

MyProject.csproj

<Project Sdk="Microsoft.NET.Sdk">    
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <ApplicationManifest>app.manifest</ApplicationManifest>
  </PropertyGroup>    
</Project>

2- Agrega el siguiente app.manifestarchivo a tu proyecto.

app.manifest

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
Alper Ebicoglu
fuente