【问题标题】:Check if user is an Administrator检查用户是否是管理员
【发布时间】:2018-02-02 20:36:45
【问题描述】:

我正在编写一个 Visual Basic .NET 桌面应用程序(目前使用 WinForms 和 .NET Framework 4.5.1)。

我需要应用检测当前windows用户是否具有系统Administrator角色,但不需要用户使用Run as administrator启动应用。

  1. 我在登录的 Windows 10 计算机上拥有 Administrator 角色。

  1. 以下代码返回machinename/ian

    将 CurrUser 调暗为 WindowsIdentity CurrUser = WindowsIdentity.GetCurrent() MsgBox(CurrUser.Name)

  2. 但是,当我测试我是否具有管理员角色时,结果是False,除非我Run as administrator

    MsgBox(My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator))

类似的问题已经在 SO 上被问过多次,但除非我使用 Run as Administrator 启动应用程序,否则解决方案(都与上述类似)返回 false。

动机

  • 该应用程序将由安装它的计算机上的不同用户使用
  • 我想对普通用户隐藏一组扩展选项,但让机器的“所有者”可以使用它们,我认为他们是具有管理员角色的用户
  • 应用程序本身不需要以提升的权限执行 - 它不应该具有更改用户系统部分的能力。从信任的角度来看,我希望我的用户知道该应用并不危险,他们不需要Run as administrator 没有任何理由。

我正在寻找一种在 Windows 10 家庭版(我认为它没有目录服务和 Active Directory?)上也能正常工作的解决方案,最好该解决方案也能在 Windows 7 上工作。

【问题讨论】:

  • 您将如何处理这些信息?在我看来,在你问的那一刻,答案或多或少是准确的,因为你需要通过 UAC 才能做任何管理员-y。
  • 这里的相关问题有一个关于通过目录服务查找组成员身份的信息的答案,我希望它在绝对基础上而不是在当前执行的上下文中是准确的:stackoverflow.com/questions/52256/…
  • @Craig - 我已经用“动机”部分更新了我的问题(我为什么要这样做)。我将看看目录服务。理想情况下,该解决方案适用于 Windows 7 和 Vista 以及 Windows 10。
  • 如果您不打算实际上强制 UAC 提示,那么这意味着这些设置/首选项实际上每个人都可以编辑,你'只是试图向非管理员隐藏(最直接的)这样做的方式。这反过来可能会给人们一种关于这些设置的错误安全感。我会认真质疑与实际上使用内置 Windows 控件保护设置相比是否值得这样做。
  • how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on 似乎有一个 C# 版本,它假定如果看到拆分令牌,则用户是管理员。翻译成 VB.Net 应该不会太棘手。

标签: .net vb.net


【解决方案1】:

注意: 以下用于测试用户是否为管理员的检查并非 100% 可靠,请参阅以下链接的“用户帐户控制 (UAC)”部分中的讨论和参考资料.


以下代码基于C#方案found herethis comment@Damien_The_Unbeliever建议)

Imports System.Runtime.InteropServices
Imports System.Security.Principal

<DllImport("advapi32.dll", SetLastError:=True)>
Private Shared Function GetTokenInformation(tokenHandle As IntPtr, tokenInformationClass As TokenInformationClass, tokenInformation As IntPtr, tokenInformationLength As Integer, ByRef returnLength As Integer) As Boolean
End Function

''' <summary>
''' Passed to <see cref="GetTokenInformation"/> to specify what
''' information about the token to return.
''' </summary>
Private Enum TokenInformationClass
    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
End Enum

''' <summary>
''' The elevation type for a user token.
''' </summary>
Private Enum TokenElevationType
    TokenElevationTypeDefault = 1
    TokenElevationTypeFull
    TokenElevationTypeLimited
End Enum




Private Function IsAdmin()
    Dim identity = WindowsIdentity.GetCurrent()
    If identity Is Nothing Then
        Throw New InvalidOperationException("Couldn't get the current user identity")
    End If
    Dim 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) Then
        Return True
    End If

    ' If we're not running in Vista onwards, we don't have to worry about checking for UAC.
    If Environment.OSVersion.Platform <> PlatformID.Win32NT OrElse Environment.OSVersion.Version.Major < 6 Then
        ' Operating system does not support UAC; skipping elevation check.
        Return False
    End If

    Dim tokenInfLength As Integer = Marshal.SizeOf(GetType(Integer))
    Dim tokenInformation As IntPtr = Marshal.AllocHGlobal(tokenInfLength)

    Try
        Dim token = identity.Token
        Dim result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, tokenInfLength)

        If Not result Then
            Dim exception = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())
            Throw New InvalidOperationException("Couldn't get token information", exception)
        End If

        Dim elevationType = DirectCast(Marshal.ReadInt32(tokenInformation), TokenElevationType)

        Select Case elevationType
            Case TokenElevationType.TokenElevationTypeDefault
                ' TokenElevationTypeDefault - User is not using a split token, so they cannot elevate.
                Return False
            Case TokenElevationType.TokenElevationTypeFull
                ' TokenElevationTypeFull - User has a split token, and the process is running elevated. Assuming they're an administrator.
                Return True
            Case TokenElevationType.TokenElevationTypeLimited
                ' TokenElevationTypeLimited - User has a split token, but the process is not running elevated. Assuming they're an administrator.
                Return True
            Case Else
                ' Unknown token elevation type.
                Return False
        End Select
    Finally
        If tokenInformation <> IntPtr.Zero Then
            Marshal.FreeHGlobal(tokenInformation)
        End If
    End Try
End Function

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-02
  • 2011-04-05
  • 2018-12-16
相关资源
最近更新 更多