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


80

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

Answers:


94
using System.Security.Principal;

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

6
请注意,如果在Vista或Win7中启用了UAC,则上述操作将无效。在这种情况下,您需要弹出一个UAC确认框并提升权限。
MisterZimbu


1
@AnkurTripathi你是...吗?
Nissim

4
除非您以管理员身份运行该应用程序,否则该代码将不起作用。
啊。

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

38
@Nissm:你们俩都同时回答了,或者距离你们都被列为张贴在“ 5分钟前”的事实相距5分钟。您没有理由攻击亚历克斯;我们不是来这里赚钱的,我们是来帮助你的。
兰道夫


14

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

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

更笼统地告诉您用户是否在提升的权限下运行。


2
这是执行此操作的最快方法的25倍
Tobias Brohl

14

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

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

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

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

https://ayende.com/blog/158401/are-you-an-administrator中检查AD的另一种方法将检查用户名是否在管理员组中。

因此,我将两者结合起来的完整方法是:

    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:如果checkCurrentRole == false,则返回true;如果checkCurrentRole == true,则返回false。

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


这真的很好,但似乎仍然不完整。如果域的全局组最终成为本地管理员组的成员,该怎么办?看来这不会匹配。我今天在家时无法测试,但回到办公室后也许会在工作中玩。
Christopher Painter

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而不具有框架或Beta框架,它将使您能够更改自己想做的事情。

然后,它将进行物理测试以避免该帐户的空值。

然后,最后它将提供检查以验证用户确实扮演了正确的角色。

我知道问题已经回答;但是我认为对于正在搜索Stack的其他任何人,我的解决方案都将是该页面的绝佳补充。我在Protected Constructor背后的理由是,您可以将此类用作派生类,从而可以控制实例化该类时的状态。



0

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

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


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文件添加到您的项目。

应用清单

<?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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.