2014-10-01 56 views
1

我需要檢查用戶是否是運行該應用程序的機器上的管理員。基本上,用戶可能會從另一臺機器提供用戶名,密碼和域名。這些通過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返回true(因此模擬工作) bRetVal也會返回true。(因此令牌是有效的)

的模擬代碼是從here(除了管理員檢查)

任何幫助將不勝感激。

+0

模仿用戶,然後獲取活動主體,再檢查'IsInRole'? – 2014-10-01 17:23:52

+0

@PeterRitchie這看起來不錯,但由於某些原因,IsInRole(WindowsBuiltInRole.Administrator)總是返回false(對於本地帳戶和域帳戶)。有任何想法嗎? – seedg 2014-10-02 07:30:56

+0

你有沒有試過[這](http://stackoverflow.com/questions/1089046/in-net-c-test-if-user-is-an-administrative-user)? – 2014-10-02 09:58:58

回答

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進行檢查,但如果服務器服務未運行,則此解決方案不起作用。

0

來自Xaruth的代碼對於TokenElevationTypeLimited是錯誤的,在這種情況下,您應該返回false,並且在管理員中構建您將獲得TokenElevationTypeDefault,因此在這種情況下,請檢查用戶是否是admin,而不是僅返回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; 
     } 
    } 
} 
相關問題