У моїй програмі потрібно запустити деякі сценарії, і я повинен бути впевнений, що користувач, який їх запускає, є адміністратором ... Який найкращий спосіб зробити це за допомогою C #?
Відповіді:
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);
Ви також можете зателефонувати до API Windows, щоб зробити це:
[DllImport("shell32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsUserAnAdmin();
що загальніше повідомляє вам, чи працює користувач із підвищеними правами.
Наведені вище відповіді з IsInRole насправді правильні: він перевіряє, чи має поточний користувач права адміністратора. Однак
Починаючи з Windows Vista, Контроль облікових записів користувачів (UAC) визначає привілеї користувача. Якщо ви є членом групи вбудованих адміністраторів, вам призначаються два маркери доступу під час виконання: стандартний маркер доступу користувача та маркер доступу адміністратора. За замовчуванням ви виконуєте стандартну роль користувача.
(із MSDN, наприклад https://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogpermission(v=vs.110).aspx )
Таким чином, IsInRole за замовчуванням розглядатиме привілеї користувача, а отже, метод повертатиме false. Істинно лише тоді, коли програмне забезпечення явно працює від імені адміністратора.
Інший метод перевірки AD на https://ayende.com/blog/158401/are-you-an-administrator перевірить, чи ім'я користувача знаходиться в групі адміністратора.
Таким чином, мій повний метод, що поєднує обидва:
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;
}
Для користувача в групі адміністратора без підвищених привілеїв (UAC увімкнено) цей метод IsCurrentUserAdmin () повертає! CheckCurrentRole: true, якщо checkCurrentRole == false, але false, якщо checkCurrentRole == true
Якщо ви запускаєте код, який вимагає прав адміністратора, розгляньте checkCurrentRole == true. В іншому випадку до того часу ви отримаєте виняток із безпеки. Тому правильна логіка IsInRole .
Просто думав, що я додам ще одне рішення; оскільки IsInRole
не завжди працює.
Залежно від ваших потреб, якщо вам потрібна підтримка старих систем; або не впевнені в тому, як ваш клієнт фізично управляє вашою системою. Це рішення, яке я впровадив; для гнучкості та змін.
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.
Отже, наведений вище код має кілька конструкцій; він фактично перевірить, чи користувач користується Vista або вище. Таким чином, якщо клієнт користується XP без фреймворку або бета-фреймворка років тому, це дозволить вам змінити те, що ви хочете зробити.
Потім буде проведено фізичний тест, щоб уникнути нульового значення для облікового запису.
Тоді в останню чергу це забезпечить перевірку, щоб переконатися, що користувач справді виконує належну роль.
Я знаю, що на це питання відповіли; але я думав, що моє рішення стане чудовим доповненням сторінки для всіх, хто шукає Stack. Мої міркування за захищеним конструктором дозволять вам використовувати цей клас як похідний клас, яким ви можете керувати станом, коли клас створюється.
Ось як я закінчую ... Я змушую свою програму працювати в режимі адміністратора. Зробити це
1- Додайте <ApplicationManifest>app.manifest</ApplicationManifest>
до свого csproj
файлу.
MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
</Project>
2- Додайте app.manifest
файл нижче до свого проекту.
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>