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

Fli*_*kov 73 c# windows-administration

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

Nis*_*sim 88

using System.Security.Principal;

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

  • 请注意,如果在Vista或Win7中启用了UAC,则上述操作无效; 在这种情况下,您需要弹出UAC确认框并提升权限. (5认同)
  • 除非您以管理员身份运行应用程序,否则该代码将无效. (3认同)
  • 不为我做错FY.I我是管理员 (2认同)

Ale*_*ort 29

return new WindowsPrincipal(WindowsIdentity.GetCurrent())
    .IsInRole(WindowsBuiltInRole.Administrator);
Run Code Online (Sandbox Code Playgroud)

  • @Nissm:你们两个都同时回答,或者在你们两个都被列为"5分钟前"发布的5分钟后接近回答.没有理由你攻击亚历克斯; 我们不是来赢得代表,我们来帮忙. (36认同)

Eri*_*Dev 12

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

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

(来自MSDN,例如https://msdn.microsoft.com/en-us/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;
    }
Run Code Online (Sandbox Code Playgroud)

对于没有提升权限的管理组中的用户(启用UAC),此方法IsCurrentUserAdmin()return!checkCurrentRole:如果checkCurrentRole == false则为true,但如果checkCurrentRole == true则为false

如果您运行需要管理员权限的代码,请考虑checkCurrentRole == true.否则,到那时你将获得一个安全例外.因此正确的IsInRole逻辑.


Ric*_*ahl 10

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

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

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

  • 这是最快的方法的 25 倍 (3认同)

Dav*_*ing 8

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

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

如果我的程序没有运行提升,并且用户是管理员,@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);
}
Run Code Online (Sandbox Code Playgroud)


And*_*ker 6

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);
}
Run Code Online (Sandbox Code Playgroud)