Sprawdź, czy aktualny użytkownik jest administratorem

82

Moja aplikacja musi uruchamiać jakieś skrypty i muszę mieć pewność, że użytkownik, który je uruchamia, jest administratorem ... Jak najlepiej to zrobić za pomocą C #?

Fliskov
źródło

Odpowiedzi:

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
źródło
6
Tylko uwaga, że ​​powyższe nie zadziała, jeśli UAC jest włączony w Vista lub Win7; w takim przypadku musisz wyświetlić okno potwierdzenia UAC i podnieść uprawnienia.
MisterZimbu
1
@AnkurTripathi Czy jesteś ...?
Nissim,
5
Ten kod nie zadziała, chyba że uruchomisz aplikację jako administrator.
AH.
35
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
Alex Reitbort
źródło
39
@Nissm: Oboje odpowiedzieliście jednocześnie lub na tyle blisko, że 5 minut po fakcie, że oboje opublikowaliście post „5 minut temu”. Nie ma powodu, żebyś atakował Alexa; nie jesteśmy tutaj, aby zdobyć reputację, jesteśmy tutaj, aby pomóc
Randolpho,
16

Możesz również wywołać interfejs API systemu Windows, aby to zrobić:

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

który bardziej ogólnie mówi, czy użytkownik działa z podwyższonymi uprawnieniami.

Rick Strahl
źródło
2
Jest to 25-krotnie najszybsza metoda zrobienia tego
Tobias Brohl
14

Powyższe odpowiedzi z IsInRole są w rzeczywistości poprawne: sprawdza, czy bieżący użytkownik ma uprawnienia administratora. Jednak,

Począwszy od systemu Windows Vista, Kontrola konta użytkownika (UAC) określa uprawnienia użytkownika. Jeśli jesteś członkiem grupy Wbudowani administratorzy, zostaną Ci przypisane dwa tokeny dostępu w czasie wykonywania: token dostępu użytkownika standardowego i token dostępu administratora. Domyślnie jesteś w standardowej roli użytkownika.

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

Dlatego IsInRole domyślnie uwzględni uprawnienia użytkownika, a zatem metoda zwróci wartość false. Prawda tylko wtedy, gdy oprogramowanie jest jawnie uruchamiane jako administrator.

Druga metoda sprawdzania AD w https://ayende.com/blog/158401/are-you-an-administrator sprawdzi, czy nazwa użytkownika znajduje się w grupie administratorów.

Moja kompletna metoda łącząca oba to:

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

Dla użytkownika w grupie administracyjnej bez podwyższonych uprawnień (włączone UAC), ta metoda IsCurrentUserAdmin () zwraca! CheckCurrentRole: true, jeśli checkCurrentRole == false, ale false if checkCurrentRole == true

Jeśli uruchamiasz kod, który WYMAGA uprawnień administratora, weź pod uwagę checkCurrentRole == true. W przeciwnym razie do tego czasu otrzymasz wyjątek bezpieczeństwa. Dlatego poprawna logika IsInRole .

EricBDev
źródło
To jest naprawdę miłe, ale nadal wydaje się niekompletne. Co by się stało, gdyby domena miała grupę globalną, która ostatecznie była członkiem lokalnej grupy administratorów? Nie wydaje się, żeby to pasowało. Nie mogę tego dzisiaj przetestować, bo jestem w domu, ale może pobawię się w pracy, kiedy wrócę do biura.
Christopher Painter
2

Pomyślałem, że dodam inne rozwiązanie; ponieważ IsInRolenie zawsze działa.

  • Jeśli użytkownik nie jest członkiem określonej grupy użytkowników systemu Windows w bieżącej sesji.
  • Administrator dokonał zmian w ustawieniach zasad grupy
  • Parametr roli jest traktowany jako metoda uwzględniająca wielkość liter.
  • A jeśli komputer XP nie ma zainstalowanej wersji .NET Framework, nie będzie działać.

W zależności od potrzeb, jeśli potrzebujesz obsługi starszych systemów; lub nie masz pewności, jak klient fizycznie zarządza Twoim systemem. To rozwiązanie, które wdrożyłem; dla elastyczności i zmian.

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.

Więc powyższy kod ma kilka konstrukcji; faktycznie przetestuje, czy użytkownik korzysta z systemu Vista lub nowszego. W ten sposób, jeśli klient korzysta z XP bez frameworka lub frameworka beta sprzed lat, pozwoli ci to zmienić to, co chciałbyś zrobić.

Następnie przeprowadzi fizyczny test, aby uniknąć wartości zerowej dla konta.

Na koniec zapewni sprawdzenie, czy użytkownik rzeczywiście pełni odpowiednią rolę.

Wiem, że odpowiedź na to pytanie; ale pomyślałem, że moje rozwiązanie byłoby świetnym dodatkiem do strony dla każdego, kto przeszukuje stos. Moje rozumowanie za Protected Constructor pozwoliłoby ci użyć tej klasy jako klasy pochodnej, którą możesz kontrolować stan, kiedy klasa jest tworzona.

Greg
źródło
0

Muszę mieć pewność, że użytkownik je obsługujący jest administratorem

Jeśli Twoja aplikacja musi być uruchamiana z uprawnieniami administratora, dobrze byłoby zaktualizować jej manifest.
Ustaw requestedExecutionlevelna requireAdminstrator.

Qwertiy
źródło
0

W ten sposób skończyłem ... Wymuszam działanie mojej aplikacji w trybie administratora. Aby to zrobić

1- Dodaj <ApplicationManifest>app.manifest</ApplicationManifest>do csprojpliku.

MyProject.csproj

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

2- Dodaj poniższy app.manifestplik do swojego projektu.

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
źródło