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 #?
Respuestas:
using System.Security.Principal;
public static bool IsAdministrator()
{
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
.IsInRole(WindowsBuiltInRole.Administrator);
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.
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 .
Solo pensé en agregar otra solución; ya IsInRole
que no siempre funciona.
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.
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 csproj
archivo.
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.manifest
archivo 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>