【问题标题】:How to check if user is an administrator on that machine如何检查用户是否是该机器上的管理员
【发布时间】:2014-10-01 16:42:15
【问题描述】:

我需要检查用户是否是运行应用程序的机器上的管理员。基本上,用户将提供用户名、密码和域,可能来自另一台机器。这些是通过 WCF 传输的,在这个阶段我需要验证提供的用户名、密码和域是否在该机器上具有管理员权限。这意味着不需要 WMI,因为一切都在本地发生(用户只需通过 WCF 将用户名、密码、域作为字符串发送)

用户可以在域中并因此链接到 Active Directory,但也可以是本地用户,这意味着我无法回复以从 Active Directory 中查找。

我设法模拟了该用户,并且可以验证该用户是本地组中的管理员。我使用以下命令对此进行了测试:

net localgroup administrators

我现在正在使用当前模拟用户创建一个 WindowsPrincipal。但是,在检查此用户是否是管理员时,我得到了错误。这是重要的代码:

// obtains user token
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, 
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

// creates duplicate token handle
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, 
    int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,  LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);

WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());

if (wp.IsInRole(WindowsBuiltInRole.Administrator))
{
    //is admin
}
else
{
    //is not an admin (I am still getting this when user is an admin)
}

bImpersonated 返回真(所以模拟工作) bRetVal 也返回 true(因此令牌有效)

模拟代码来自here(管理员检查除外)

任何帮助将不胜感激。

【问题讨论】:

  • 冒充用户,然后获取活动主体,然后检查IsInRole?
  • @PeterRitchie 这看起来不错,但由于某种原因 IsInRole(WindowsBuiltInRole.Administrator) 总是返回 false(对于本地帐户和域帐户)。有什么想法吗?
  • 你试过this吗?

标签: c# security authentication


【解决方案1】:

我使用令牌检查:

private static Boolean IsAdministratorByToken(WindowsIdentity identity)
{
    WindowsPrincipal principal = new WindowsPrincipal(identity);

    // Check if this user has the Administrator role. If they do, return immediately.
    // If UAC is on, and the process is not elevated, then this will actually return false.
    if (principal.IsInRole(WindowsBuiltInRole.Administrator))
    {
        return true;
    }

    // If we're not running in Vista onwards, we don't have to worry about checking for UAC.
    if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6)
    {
        // Operating system does not support UAC; skipping elevation check.
        return false;
    }

    int tokenInfLength = Marshal.SizeOf(typeof(int));
    IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);

    try
    {
        IntPtr token = identity.Token;
        Boolean result = NativeMethods.GetTokenInformation(token, NativeMethods.TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, out tokenInfLength);

        if (!result)
        {
            Exception exception = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            throw new InvalidOperationException("Couldn't get token information", exception);
        }

        NativeMethods.TokenElevationType elevationType = (NativeMethods.TokenElevationType)Marshal.ReadInt32(tokenInformation);

        switch (elevationType)
        {
            case NativeMethods.TokenElevationType.TokenElevationTypeDefault:
                // TokenElevationTypeDefault - User is not using a split token, so they cannot elevate.
                return false;

            case NativeMethods.TokenElevationType.TokenElevationTypeFull:
                // TokenElevationTypeFull - User has a split token, and the process is running elevated. Assuming they're an administrator.
                return true;

            case NativeMethods.TokenElevationType.TokenElevationTypeLimited:
                // TokenElevationTypeLimited - User has a split token, but the process is not running elevated. Assuming they're an administrator.
                return true;

            default:
                // Unknown token elevation type.
                return false;
        }
    }
    finally
    {
        if (tokenInformation != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(tokenInformation);
        }
    }
}

这是来自this blog

您也可以使用PrincipalContext 进行检查,但如果服务器服务未运行,此解决方案将不起作用。

【讨论】:

    【解决方案2】:

    Xaruth 的代码关于 TokenElevationTypeLimited 是错误的,在这种情况下,您应该返回 false,并且对于内置管理员,您将获得 TokenElevationTypeDefault,因此在这种情况下,请检查用户是否是管理员而不是仅返回 false。 这是这篇文章的代码: https://candritzky.wordpress.com/2012/08/28/uac-elevation-and-the-default-administrator-account/

    /// <summary>
    /// Base on code found here:
    /// http://stackoverflow.com/questions/1220213/c-detect-if-running-with-elevated-privileges
    /// </summary>
    public static class UacHelper
    {
        private const string uacRegistryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System";
        private const string uacRegistryValue = "EnableLUA";
    
        private const uint STANDARD_RIGHTS_READ = 0x00020000;
        private const uint TOKEN_QUERY = 0x0008;
        private const uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
    
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass,
            IntPtr TokenInformation, uint TokenInformationLength,
            out uint ReturnLength);
    
        public enum TOKEN_INFORMATION_CLASS
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin,
            TokenElevationType,
            TokenLinkedToken,
            TokenElevation,
            TokenHasRestrictions,
            TokenAccessInformation,
            TokenVirtualizationAllowed,
            TokenVirtualizationEnabled,
            TokenIntegrityLevel,
            TokenUIAccess,
            TokenMandatoryPolicy,
            TokenLogonSid,
            MaxTokenInfoClass
        }
    
        public enum TOKEN_ELEVATION_TYPE
        {
            TokenElevationTypeDefault = 1,
            TokenElevationTypeFull,
            TokenElevationTypeLimited
        }
    
        private static bool? _isUacEnabled;
    
        public static bool IsUacEnabled
        {
            get
            {
                if (_isUacEnabled == null)
                {
                    var uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false);
                    if (uacKey == null)
                    {
                        _isUacEnabled = false;
                    }
                    else
                    {
                        var enableLua = uacKey.GetValue(uacRegistryValue);
                        _isUacEnabled = enableLua.Equals(1);
                    }
                }
                return _isUacEnabled.Value;
            }
        }
    
        private static bool? _isAdministrator;
    
        public static bool IsAdministrator
        {
            get
            {
                if (_isAdministrator == null)
                {
                    var identity = WindowsIdentity.GetCurrent();
                    Debug.Assert(identity != null);
                    var principal = new WindowsPrincipal(identity);
                    _isAdministrator = principal.IsInRole(WindowsBuiltInRole.Administrator);
                }
                return _isAdministrator.Value;
            }
        }
    
        private static bool? _isProcessElevated;
    
        public static bool IsProcessElevated
        {
            get
            {
                if (_isProcessElevated == null)
                {
                    if (IsUacEnabled)
                    {
                        var process = Process.GetCurrentProcess();
    
                        IntPtr tokenHandle;
                        if (!OpenProcessToken(process.Handle, TOKEN_READ, out tokenHandle))
                        {
                            throw new ApplicationException("Could not get process token.  Win32 Error Code: " +
                                                           Marshal.GetLastWin32Error());
                        }
    
                        var elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;
    
                        var elevationResultSize = Marshal.SizeOf((int) elevationResult);
                        uint returnedSize;
                        var elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);
    
                        var success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType,
                            elevationTypePtr, (uint) elevationResultSize, out returnedSize);
                        if (!success)
                        {
                            Marshal.FreeHGlobal(elevationTypePtr);
                            throw new ApplicationException("Unable to determine the current elevation.");
                        }
    
                        elevationResult = (TOKEN_ELEVATION_TYPE) Marshal.ReadInt32(elevationTypePtr);
                        Marshal.FreeHGlobal(elevationTypePtr);
    
                        // Special test for TokenElevationTypeDefault.
                        // If the current user is the default Administrator, then the
                        // process is also assumed to run elevated. This is assumed 
                        // because by default the default Administrator (which is disabled by default) 
                        //  gets all access rights even without showing a UAC prompt.
                        switch (elevationResult)
                        {
                            case TOKEN_ELEVATION_TYPE.TokenElevationTypeFull:
                                _isProcessElevated = true;
                                break;
                            case TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited:
                                _isProcessElevated = false;
                                break;
                            default:
                                // Will come here if either
                                // 1. We are running as the default Administrator.
                                // 2. We were started using "Run as administrator" from a non-admin
                                //    account and logged on as the default Administrator account from
                                //    the list of available Administrator accounts.
                                //
                                // Note: By default the default Administrator account always behaves 
                                //       as if UAC was turned off. 
                                //
                                // This can be controlled through the Local Security Policy editor 
                                // (secpol.msc) using the 
                                // "User Account Control: Use Admin Approval Mode for the built-in Administrator account"
                                // option of the Security Settings\Local Policies\Security Options branch.
                                _isProcessElevated = IsAdministrator;
                                break;
                        }
                    }
                    else
                    {
                        _isProcessElevated = IsAdministrator;
                    }
                }
                return _isProcessElevated.Value;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-02
      • 2022-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      相关资源
      最近更新 更多