检查当前用户是否为管理员

发布于 2024-09-16 16:34:42 字数 63 浏览 3 评论 0原文

我的应用程序需要运行一些脚本,并且我必须确保运行它们的用户是管理员...使用 C# 执行此操作的最佳方法是什么?

My application needs to run some scripts, and I must be sure that the user running them is an administrator... What is the best way of doing this using C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

青丝拂面 2024-09-23 16:34:42
using System.Security.Principal;

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

public static bool IsAdministrator()
{
    using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}
巾帼英雄 2024-09-23 16:34:42
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
只等公子 2024-09-23 16:34:42

您还可以调用 Windows API 来执行此操作:

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

它更一般地告诉您用户是否在提升的权限下运行。

You can also call into the Windows API to do this:

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

which more generically tells you whether user is running under elevated rights.

蓝海 2024-09-23 16:34:42

上面的 IsInRole 答案实际上是正确的:它确实检查当前用户是否具有管理员权限。
然而,

从 Windows Vista 开始,用户帐户控制 (UAC) 确定用户的权限。如果您是内置管理员组的成员,则会为您分配两个运行时访问令牌:标准用户访问令牌和管理员访问令牌。默认情况下,您具有标准用户角色。

(来自 MSDN,例如 https:/ /msdn.microsoft.com/en-us/library/system.diagnostics.eventlogpermission(v=vs.110).aspx)

因此,IsInRole 将默认情况下考虑用户权限,因此该方法返回 false。仅当软件明确以管理员身份运行时才正确。

另一种方法检查 https://ayende.com/blog/158401/are 中的 AD -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() return !checkCurrentRole: true if checkCurrentRole==false, but false if checkCurrentRole==true

如果运行代码需要管理员权限,请考虑 checkCurrentRole==true。否则,届时您将收到安全异常。
因此,正确的 IsInRole 逻辑。

The above answers with IsInRole are actually correct: it does check if the current user has admin privilege.
However,

Starting with Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role.

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

Thus, IsInRole will per default consider the user privilege, and thus the method return false. Only true when the software is explicitly run as administrator.

The other method checking AD in https://ayende.com/blog/158401/are-you-an-administrator will check if the user name is in an admin group.

My complete method combining both is thus:

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

For a user in an admin group without elevated privilege (UAC enabled), this method IsCurrentUserAdmin() return !checkCurrentRole: true if checkCurrentRole==false, but false if checkCurrentRole==true

If you run code that REQUIRES admin privilege, consider the checkCurrentRole==true. Otherwise, you'll get a security exception by then.
Therefore the correct IsInRole logic.

一片旧的回忆 2024-09-23 16:34:42

与这里的其他程序一样,我的程序没有以提升的方式运行,因此如果启用了 UAC,此代码将返回 false

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

@EricBDev 的 IsAdministratorNoCache 答案确实返回 true如果我的程序没有运行提升,并且用户是管理员。然而,正如博客作者所说,它非常慢。

这是我的解决方案;它模拟 IsAdministratorNoCache 但速度很快:

private bool IsCurrentUserInAdminGroup()
{
    // https://learn.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);
}

Like others here, my program is not running elevated, so this code returns false if UAC is enabled:

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

@EricBDev's answer with IsAdministratorNoCache does return true if my program is not running elevated, and the user is an Admin. However, like the blog author says, it is very slow.

Here is my solution; it emulates IsAdministratorNoCache but is fast:

private bool IsCurrentUserInAdminGroup()
{
    // https://learn.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);
}
东风软 2024-09-23 16:34:42

David Ching 的答案很好 - 但给您留下了管理员组的硬编码 ID。这有点清楚了:

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

The answer by David Ching is good - but leaves you with a hardcoded ID for the Admin group. This is a bit clearer:

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);
}
还在原地等你 2024-09-23 16:34:42

只是想我会添加另一个解决方案;因为 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 的人来说将是一个很好的补充。我对受保护构造函数的推理将允许您使用此类作为派生类,您可以控制该类实例化时的状态。

Just thought I'd add another solution; as the IsInRole doesn't always work.

  • If the user isn't a member of the specified Windows User Group in the current session.
  • The administrator has made changes in the Group Policy Settings
  • The role parameter is treated as a 'Case Sensitive' method.
  • And if an XP machine doesn't have the .NET Framework Version installed it won't work.

Depending on your needs if you need to support older systems; or are unsure of how your client is physically managing your system. This is a solution I implemented; for flexibility and alterations.

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.

So the above code has a few constructs; it will actually test to see if the User is on Vista or higher. That way if a customer is on XP without a framework or beta framework from years ago it will allow you to alter what you'd like to do.

Then it will physically test to avoid a null value for the account.

Then last of all it will provide the check to verify that the user is indeed in the proper role.

I know the question has been answered; but I thought my solution would be a great addition to the page for anyone else whom is searching Stack. My reasoning behind the Protected Constructor would allow you to use this class as a Derived Class that you could control the state of when the class is instantiated.

[旋木] 2024-09-23 16:34:42
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, out TOKEN_ELEVATION TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);


    static bool IsProcessElevated()
    {
        bool fIsElevated = false;
        IntPtr hToken = IntPtr.Zero;
        TOKEN_ELEVATION elevation;
        uint dwSize;

        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out hToken))
        {
            Debug.LogError("Failed to get Process Token: " + Marshal.GetLastWin32Error());
            goto Cleanup; // if Failed, we treat as False
        }

        if (!GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, out elevation, (uint)Marshal.SizeOf(typeof(TOKEN_ELEVATION)), out dwSize))
        {
            Debug.LogError("Failed to get Token Information: " + Marshal.GetLastWin32Error());
            goto Cleanup; // if Failed, we treat as False
        }

        fIsElevated = elevation.TokenIsElevated;

    Cleanup:
        if (hToken != IntPtr.Zero)
        {
            CloseHandle(hToken);
            hToken = IntPtr.Zero;
        }
        return fIsElevated;
    }

    const uint TOKEN_QUERY = 0x0008;

    enum TOKEN_INFORMATION_CLASS
    {
        TokenElevation = 20
    }

    struct TOKEN_ELEVATION
    {
        [MarshalAs(UnmanagedType.Bool)]
        public bool TokenIsElevated;
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentProcess();
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, out TOKEN_ELEVATION TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);


    static bool IsProcessElevated()
    {
        bool fIsElevated = false;
        IntPtr hToken = IntPtr.Zero;
        TOKEN_ELEVATION elevation;
        uint dwSize;

        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out hToken))
        {
            Debug.LogError("Failed to get Process Token: " + Marshal.GetLastWin32Error());
            goto Cleanup; // if Failed, we treat as False
        }

        if (!GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, out elevation, (uint)Marshal.SizeOf(typeof(TOKEN_ELEVATION)), out dwSize))
        {
            Debug.LogError("Failed to get Token Information: " + Marshal.GetLastWin32Error());
            goto Cleanup; // if Failed, we treat as False
        }

        fIsElevated = elevation.TokenIsElevated;

    Cleanup:
        if (hToken != IntPtr.Zero)
        {
            CloseHandle(hToken);
            hToken = IntPtr.Zero;
        }
        return fIsElevated;
    }

    const uint TOKEN_QUERY = 0x0008;

    enum TOKEN_INFORMATION_CLASS
    {
        TokenElevation = 20
    }

    struct TOKEN_ELEVATION
    {
        [MarshalAs(UnmanagedType.Bool)]
        public bool TokenIsElevated;
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr GetCurrentProcess();
掌心的温暖 2024-09-23 16:34:42

我必须确保运行它们的用户是管理员

如果您的应用程序必须以管理员权限运行,则更新其清单是正确的。
requestedExecutionlevel 设置为 requireAdminstrator

I must be sure that the user running them is an administrator

If your application must be run with admin rights, it would be right to update its manifest.
Set requestedExecutionlevel to requireAdminstrator.

不一样的天空 2024-09-23 16:34:42

这就是我的结局...
我强制我的应用程序以管理员模式运行。
为此,请执行以下操作:

1- 将 app.manifest 添加到您的 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 文件添加到您的项目中。

应用程序清单

<?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>

This is how I end up...
I'm forcing my app to run as administrator mode.
To do this

1- Add <ApplicationManifest>app.manifest</ApplicationManifest> to your csproj file.

MyProject.csproj

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

2- Add the below app.manifest file to your project.

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文