Проверьте, является ли текущий пользователь администратором

Мое приложение должно запускать некоторые сценарии, и я должен быть уверен, что пользователь, выполняющий их, является администратором... Каков наилучший способ сделать это с помощью C#?

9 ответов

Решение
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);

Вы также можете вызвать Windows API для этого:

[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.

Как и другие здесь, моя программа не работает с повышенными привилегиями, поэтому этот код возвращает falseвключен ли UAC:

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

Ответ @EricBDev с возвратом trueесли моя программа не работает с повышенными правами, а пользователь является администратором. Однако, как говорит автор блога, это очень медленно.

Вот мое решение; он подражает IsAdministratorNoCacheно быстро:

      private bool IsCurrentUserInAdminGroup()
{
    // https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/security-identifiers-in-windows
    // S-1-5-32-544
    // A built-in group. After the initial installation of the operating system,
    // the only member of the group is the Administrator account.
    // When a computer joins a domain, the Domain Admins group is added to
    // the Administrators group. When a server becomes a domain controller,
    // the Enterprise Admins group also is added to the Administrators group.
    var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
    var claims = principal.Claims;
    return (claims.FirstOrDefault(c => c.Value == "S-1-5-32-544") != null);
}

Ответ Дэвида Чинга хорош, но оставляет вам жестко закодированный идентификатор для группы администраторов. Это немного яснее:

      private bool IsCurrentUserInAdminGroup()
{
    var claims = new WindowsPrincipal(WindowsIdentity.GetCurrent()).Claims;
    var adminClaimID = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).Value;
    return claims.Any(c => c.Value == adminClaimID);
}

Просто подумал, что добавлю другое решение; как IsInRole не всегда работает

  • Если пользователь не является членом указанной группы пользователей Windows в текущем сеансе.
  • Администратор внес изменения в параметры групповой политики.
  • Параметр роли обрабатывается как метод с учетом регистра.
  • И если на машине с XP не установлена ​​версия.NET Framework, она не будет работать.

В зависимости от ваших потребностей, если вам нужно поддерживать старые системы; или не уверены, как ваш клиент физически управляет вашей системой. Это решение, которое я реализовал; для гибкости и переделок.

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 без фреймворка или бета-фреймворка много лет назад, это позволит вам изменить то, что вы хотели бы сделать.

Затем он будет физически проверен, чтобы избежать нулевого значения для учетной записи.

Затем, в конце концов, он предоставит проверку, чтобы убедиться, что пользователь действительно играет надлежащую роль.

Я знаю, что на вопрос был дан ответ; но я думал, что мое решение будет отличным дополнением к странице для всех, кто ищет в стеке. Мои рассуждения о Защищенном конструкторе позволили бы вам использовать этот класс в качестве производного класса, в котором вы можете контролировать состояние, когда создается экземпляр класса.

Я должен быть уверен, что пользователь, выполняющий их, является администратором

Если ваше приложение должно быть запущено с правами администратора, было бы правильно обновить его манифест.
Задавать requestedExecutionlevel в requireAdminstrator,

Вот как я закончил... Я заставляю свое приложение запускаться в режиме администратора. Сделать это

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>
Другие вопросы по тегам