vb.net 将用户名转换为 WindowsIdentity?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21976322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 16:52:28  来源:igfitidea点击:

Convert UserName to WindowsIdentity?

c#.netvb.netadminuser-accounts

提问by ElektroStudios

I've tagged this question with C#because is part of .NETand is known that some people can programming and understand without problems both VB.NETand C#as one, and I should not have problems to translate the C#instructions to VB.NETthen I would be happy with a solution written in one of those languages.

我已经标记了这个问题,C#因为它是一部分,.NET并且众所周知,有些人可以毫无问题地进行编程和理解,VB.NET并且C#作为一个整体,我应该没有问题来翻译C#指令,VB.NET然后我会很高兴用一个解决方案编写那些语言。



I would like to specify an username in this function to retrieve if it's an Admin or not, what changes I should do?

我想在这个函数中指定一个用户名来检索它是否是管理员,我应该怎么做?

MsgBox(UserIsAdmin("Elektro"))

' ByVal UserName as String or other needed object.
Public Function UserIsAdmin(ByVal UserName As XXXX) As Boolean 

    Dim Identity As Security.Principal.WindowsIdentity =
    Security.Principal.WindowsIdentity.FromUserName(UserName)

    Return New Security.Principal.WindowsPrincipal(Identity).
               IsInRole(Security.Principal.WindowsBuiltInRole.Administrator)

End Function

PS: Ofcourse the FromUserNamemethod does not exist.

PS:当然这个FromUserName方法不存在。



UPDATE

更新

I'm just trying @meziantou approach but I always get an exception about the username structure or about the network entry is not found, but, anyways, this is not exactlly what I'm looking for (I mean specify a domain or computername or whatever else that is not done automated by the function).

我只是在尝试@meziantou 方法,但我总是遇到有关用户名结构或未找到网络条目的异常,但是,无论如何,这并不是我正在寻找的(我的意思是指定域或计算机名或其他任何不是由该功能自动完成的)。

Public Class Form

Private Sub Test() Handles MyBase.Shown

    ' Things that I've tried:

    MsgBox(UserIsAdmin("Administrador")) ' Username
    MsgBox(UserIsAdmin("[email protected]")) ' Username@LocalHost
    MsgBox(UserIsAdmin(Security.Principal.WindowsIdentity.GetCurrent().Name)) ' DomainName\Username
    MsgBox(UserIsAdmin("Administrador@ELEKTRO")) ' Username@DomainName
    MsgBox(UserIsAdmin(Security.Principal.WindowsIdentity.GetCurrent.User.Value)) ' The SID

End Sub

''' <summary>
''' Determines whether an user is an Administrator.
''' </summary>
''' <returns><c>true</c> if the user is an Administrator, <c>false</c> otherwise.</returns>
Public Function UserIsAdmin(Optional ByVal UserName As String = String.Empty) As Boolean

    Dim Identity As Security.Principal.WindowsIdentity =
        If(Not String.IsNullOrEmpty(UserName),
           New Security.Principal.WindowsIdentity(UserName),
           Security.Principal.WindowsIdentity.GetCurrent())

    Return New Security.Principal.WindowsPrincipal(Identity).
               IsInRole(Security.Principal.WindowsBuiltInRole.Administrator)

End Function

End Class


UPDATE 2

更新 2

I'm trying the @Frinavale approach but I'm not able to adapt this code to retrieve the information that I'm interested to.

我正在尝试 @Frinavale 方法,但我无法调整此代码来检索我感兴趣的信息。

Imports System.DirectoryServices.AccountManagement
Imports System.Security.Principal

Public Class Form1

    Private Sub Test() Handles MyBase.Shown

        Dim pContext As PrincipalContext = New PrincipalContext(ContextType.Machine)
        Dim pUsers As Principal = New UserPrincipal(pContext)
        Dim pSearcher As PrincipalSearcher = New PrincipalSearcher(pUsers)

        For Each User As Principal In pSearcher.FindAll()

            For Each Group As Principal In User.GetGroups
                ' Result of 'Administrators' (in Spanish): 'Administradores', 
                ' so this is not efficient to compare.
                MsgBox(Group.Name)
            Next

            ' Any of these works:
            ' It throws an exception because 
            ' i'm not passing the expected parameter for a WindowsIdentity.

            MsgBox(UserIsAdmin(User.Name))
            ' MsgBox(UserIsAdmin(User.UserPrincipalName))
            ' MsgBox(UserIsAdmin(User.DistinguishedName))
            ' MsgBox(UserIsAdmin(User.SamAccountName))

        Next User

    End Sub

    Public Function UserIsAdmin(ByVal User As String) As Boolean

        Using Identity As New WindowsIdentity(User)
            Return New WindowsPrincipal(Identity).IsInRole(WindowsBuiltInRole.Administrator)
        End Using

    End Function

End Class

回答by Frinavale

You can use the GroupPrincipal Classto retrieve all users that are part of the administrator group. Once you have all the members, you can determine if the user is in the group by comparing the member's name to the user name provided.

您可以使用GroupPrincipal 类来检索属于管理员组的所有用户。拥有所有成员后,您可以通过将成员的名称与提供的用户名进行比较来确定用户是否在组中。

For example:

例如:

Public Function UserIsAdmin(ByVal userName As String) As Boolean
        Dim groupName As String = "administrators" '<--You can localize this'
        Dim isAdmin As Boolean
        Using context As PrincipalContext = New PrincipalContext(ContextType.Machine)
            Dim gfilter As GroupPrincipal = GroupPrincipal.FindByIdentity(context, groupName)
            If gfilter IsNot Nothing Then
                Dim members = gfilter.GetMembers
                For Each member In members
                    If String.Compare(member.Name, userName, True) = 0 Then
                        isAdmin = True
                    End If
                Next
            End If
        End Using
        Return isAdmin
End Function

I know that you mentioned that the group's name is localized (which hasn't occurred for me because I'm using an US English operating system/environment). In that case I recommend that you look into the topic of Globalization(store store a localized version of "administrators" into resource files with the key being "administrators" and then retrieve the appropriate text for "administrator" based on the culture that you are working in)

我知道您提到该组的名称已本地化(这对我来说没有发生,因为我使用的是美国英语操作系统/环境)。在这种情况下,我建议您查看全球化主题(将“管理员”的本地化版本存储到资源文件中,键为“管理员”,然后根据您所在的文化检索“管理员”的适当文本在工作)

回答by meziantou

To get a WindowsIdentityfrom a user name, you can use the WindowsIdentityconstructor (http://msdn.microsoft.com/en-us/library/td3046fc(v=vs.110).aspx)

要从WindowsIdentity用户名中获取 a ,您可以使用WindowsIdentity构造函数(http://msdn.microsoft.com/en-us/library/td3046fc(v=vs.110).aspx

Dim windowsIdentity = New WindowsIdentity("administrator")
New WindowsPrincipal(windowsIdentity).IsInRole(WindowsBuiltInRole.Administrator)

回答by ElektroStudios

MSDN says that a WindowsIdentityobject can be only a logged user, so seems impossible to do the username conversion that I wanted, but, this is a working solution:

MSDN 说WindowsIdentity对象只能是登录用户,因此似乎不可能进行我想要的用户名转换,但是,这是一个可行的解决方案:

' User Is Admin?
'
' Instructions:
' 1. Add a reference to 'System.DirectoryServices.AccountManagement'.
' 2. Imports System.DirectoryServices.AccountManagement
'
' Example Usages:
' MsgBox(UserIsAdmin("Administrador"))
' MsgBox(UserIsAdmin(New Security.Principal.SecurityIdentifier("S-1-5-21-250596608-219436059-1115792336-500")))
'
''' <summary>
''' Determines whether an User is an Administrator, in the current machine.
''' </summary>
''' <param name="UserName">Indicates the account Username.</param>
''' <returns><c>true</c> if user is an Administrator, <c>false</c> otherwise.</returns>
Public Function UserIsAdmin(ByVal UserName As String) As Boolean

    Dim AdminGroupSID As New SecurityIdentifier("S-1-5-32-544")

    Dim pContext As New PrincipalContext(ContextType.Machine)
    Dim pUser As New UserPrincipal(pContext)
    Dim pSearcher As New PrincipalSearcher(pUser)

    Dim User As Principal =
        (From u As Principal In pSearcher.FindAll
        Where u.Name.Equals(UserName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault

    If User Is Nothing Then
        Throw New Exception(String.Format("User with name '{0}' not found.", UserName))
    End If

    Dim IsAdmin As Boolean =
        (From Group As GroupPrincipal In User.GetGroups
         Where Group.Sid = AdminGroupSID).Any

    pContext.Dispose()
    pSearcher.Dispose()
    pUser.Dispose()

    Return IsAdmin

End Function