2014-02-23 56 views
0

我已经标记了这个问题与C#因为是.NET一部分,众所周知,有些人可以编程,没有问题了解双方VB.NETC#为一体,我不应该有问题,翻译C#指令VB.NET然后我会对用这些语言之一编写的解决方案感到满意。将用户名转换为WindowsIdentity?


我想在此功能指定的用户名来检索,如果它是一个管理员或没有什么变化,我应该怎么办?

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:当然FromUserName方法不存在。


UPDATE

我只是想@meziantou的方法,但我总是对用户名结构或有关网络条目中找不到一个例外,但是,不管怎么说,这不是确切地说我在找什么(我的意思是指定一个域或computername或其他任何不是由函数自动完成的)。

Public Class Form 

Private Sub Test() Handles MyBase.Shown 

    ' Things that I've tried: 

    MsgBox(UserIsAdmin("Administrador")) ' Username 
    MsgBox(UserIsAdmin("[email protected]")) ' [email protected] 
    MsgBox(UserIsAdmin(Security.Principal.WindowsIdentity.GetCurrent().Name)) ' DomainName\Username 
    MsgBox(UserIsAdmin("[email protected]")) ' [email protected] 
    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 

更新2

我尝试@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 
+1

您应该考虑使用PrincipalSearcher检索所有主体对象的集合(使用PrincipalSearcher。FindAll)并从那里确定哪个Principal具有您正在查找的身份。 (PrincipalSearcher信息:http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.principalsearcher%28v=vs.110%29.aspx)(FindAll信息: http:// msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.principalsearcher.findall%28v=vs.110%29.aspx) – Frinavale

+0

@Frinavale谢谢,但我找不到适应它的方式。我试图传递给搜索者的名字给这个函数,但仍然说这个名字是不正确的。所以我试图直接在搜索器中检查用户是否是管理员,获取组“GetGroups”方法,但我看到的是“Administrators”组的名称是语言相关的,因此在我的语言中是完全的不同的名字,然后比较名称是不高效的。我能做什么?如果你愿意的话,请看我最新的问题。 thankyou – ElektroStudios

+0

必须解决这个本地化问题。 “IsInRole”方法需要一个字符串,所以不要使用WindowsBuiltInRole.Administrator尝试传入“Administrator”(当然,我假设“Administrator”以英文存储......如果不是,比你将不得不使用资源正确地本地化单词,以便它匹配) – Frinavale

回答

3

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

例如:

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 

我知道你提到,该集团的名称是局部的(因为我使用的是美国英语操作系统/环境未发生对我来说)。在这种情况下,我建议您查看Globalization(将“管理员”的本地化版本存储到资源文件中,密钥为“管理员”,然后根据您所在的文化检索“管理员”的相应文本工作中)

+0

我不明白如何本地化管理员组的正式名称,MSDN网址似乎没有关于我的问题的信息,请问您可以举个例子吗?我需要这个'UserIsAdmin'作为通用解决方案。 – ElektroStudios

+0

在我们开始讨论全球化这个大问题之前。以上功能对你有用吗?如果没有,你尝试设置'groupName =“Administradors”'?那工作?上面的代码适用于我,但我在Windows 7操作系统上使用美国 - 英国文化,听起来您正在系统上使用西班牙文化,将“管理员”转换为“Administradors”,您需要补偿这个。 – Frinavale

+1

不,你的代码应该只适用于我们的语言(“管理员”),无论如何,遵循你对“Principal”和“GroupPrincipal”的使用的建议并进行更多的研究我发现了另一种方法,只是比较SID组,我的意思是管理员组SID,我用我写过的解决方案回答了这个问题,如果有人感兴趣。感谢帮助。 – ElektroStudios

2

为了得到一个用户名的WindowsIdentity,则可以使用WindowsIdentity构造(http://msdn.microsoft.com/en-us/library/td3046fc(v=vs.110).aspx

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

谢谢,但它在我的情况下引发异常,它说,提供的名称不是一个帐户名称与正确的结构,所以我也试着指定像UserIsAdmin(“MyPCName \ MyUserName”)这样的域名,但是仍然会抛出异常,但是如果引发异常,那么我仍然想要做的只是在方法参数中只指定用户名而不是域名。 – ElektroStudios

+1

该构造函数指示重载需要一个'User Principal Name'(UPN)字符串,不仅是一个用户名,我将阐明我的意图是将一个用户名传递给该方法,以便该方法解析该域,反正我想通过一个UPN字符串没有成功(这是我第一次尝试这个):'UserIsAdmin(“[email protected]”)' – ElektroStudios

+0

这个例子在我的机器上工作,也许是因为我的机器是一个域的成员 – meziantou

1

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