Перевірте, чи поточним користувачем є адміністратор


82

У моїй програмі потрібно запустити деякі сценарії, і я повинен бути впевнений, що користувач, який їх запускає, є адміністратором ... Який найкращий спосіб зробити це за допомогою C #?

Відповіді:


96
using System.Security.Principal;

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

6
Тільки зверніть увагу, що вищезазначене не буде працювати, якщо UAC увімкнено в Vista або Win7; вам потрібно буде відкрити вікно підтвердження UAC і підвищити дозволи в такому випадку.
MisterZimbu


1
@AnkurTripathi Ви ...?
Ніссім

5
Цей код не буде працювати, якщо ви не запустите програму як адміністратор.
Ага.

35
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);

39
@Nissm: Ви обидва відповіли одночасно, або майже настільки, що через 5 хвилин після того, як ви обоє перерахували, що опублікували "5 хвилин тому". У вас немає причин нападати на Алекса; ми не тут, щоб заробити репутацію, ми тут, щоб допомогти.
Randolpho


16

Ви також можете зателефонувати до API Windows, щоб зробити це:

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

що загальніше повідомляє вам, чи працює користувач із підвищеними правами.


2
Це в 25 разів найшвидший спосіб зробити це
Тобіас

14

Наведені вище відповіді з 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 .


Це дійсно приємно, але все ще здається неповним. Що робити, якщо домен мав глобальну групу, яка в кінцевому рахунку була членом групи місцевих адміністраторів? Здається, це не відповідало б. Я не можу перевірити це сьогодні, оскільки я вдома, але, можливо, я пограю з цим на роботі, коли повернусь в офіс.
Крістофер Пейнтер

2

Просто думав, що я додам ще одне рішення; оскільки 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 без фреймворку або бета-фреймворка років тому, це дозволить вам змінити те, що ви хочете зробити.

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

Тоді в останню чергу це забезпечить перевірку, щоб переконатися, що користувач справді виконує належну роль.

Я знаю, що на це питання відповіли; але я думав, що моє рішення стане чудовим доповненням сторінки для всіх, хто шукає Stack. Мої міркування за захищеним конструктором дозволять вам використовувати цей клас як похідний клас, яким ви можете керувати станом, коли клас створюється.



0

Я повинен бути впевнений, що користувач, який їх запускає, є адміністратором

Якщо ваша програма повинна запускатися з правами адміністратора, було б правильно оновити її маніфест.
Набір requestedExecutionlevelдля requireAdminstrator.


0

Ось як я закінчую ... Я змушую свою програму працювати в режимі адміністратора. Зробити це

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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.