2010-08-12 50 views
2

當與如何檢查NTAccount對象是否代表組或用戶?

GetAccessRules(True, True, GetType(System.Security.Principal.NTAccount)) 

我怎麼能告訴我們,如果在每個規則中引用的NTACCOUNT對象是用戶帳戶或組返回的訪問規則的工作?

更新:

我能解決這個問題如下。請注意,如果NTAccount是一個組,則此代碼的意圖是返回True,否則或在檢查過程中發生錯誤時返回False

有沒有更好的方法來做到這一點?

Public Function IsGroup(ByVal account As NTAccount) as Boolean 
    Dim samAccountName as string = account.Value 
    Dim accountNameParts() As String = samAccountName.Split("\") 
    If accountNameParts.Count() = 2 Then 
     Dim principalContext As PrincipalContext 
     Try 
      principalContext = New PrincipalContext(ContextType.Domain, accountNameParts(0)) 
     Catch 
      Try 
       principalContext = New PrincipalContext(ContextType.Machine, accountNameParts(0)) 
      Catch 
       principalContext = Nothing 
      End Try 
     End Try 
     If Not principalContext Is Nothing Then 
      Dim principal As Principal 
      principal = principal.FindByIdentity(principalContext, _samAccountName) 
      If Not principal Is Nothing then 
       return TypeOf principal Is GroupPrincipal 
      End If 
     End If 
    End If 
    Return False 
End Function 

另一個更新:

上述解決方案是好的大多數服務器\帳戶對象,但對於本地組,我們有的EMC Celerra NAS服務器上的對象失敗。我試圖使用NetUserGetInfo/NetLocalGroupGetInfo Win API調用來查看這是否可行,但我無法讓它們正常工作。有關更多詳細信息,請參閱NetUserGetInfo/NetLocalGroupGetInfo returning error 1722

+0

我已經完成了現在。謝謝。 – 2010-09-17 03:39:46

回答

1

對此的答案確實是使用Windows API(NetUserGetInfoNetLocalGroupGetInfo)。

Class NetApi 
    Private Declare Unicode Function NetUserGetInfo Lib "Netapi32.dll" (_ 
     ByVal ServerName As String, _ 
     ByVal UserName As String, _ 
     ByVal level As Integer, _ 
     ByRef BufPtr As IntPtr) As Integer 

    Private Declare Unicode Function NetLocalGroupGetInfo Lib "Netapi32.dll" (_ 
     ByVal ServerName As String, _ 
     ByVal GroupName As String, _ 
     ByVal level As Integer, _ 
     ByRef BufPtr As IntPtr) As Integer 

    Declare Unicode Function NetApiBufferFree Lib "netapi32.dll" _ 
    (ByRef buffer As IntPtr) As Long 

    Public Shared Function PrincipalIsGroup(ByVal MachineName As String, ByVal AccountName As String) As String 
     If String.IsNullOrEmpty(MachineName) Then 
      Throw New ArgumentException("MachineName is Required") 
     End If 
     If String.IsNullOrEmpty(AccountName) Then 
      Throw New ArgumentException("AccountName is Required") 
     End If 
     Dim returnValue As String = "NotFound" 
     Dim bufPtr As IntPtr 
     Dim lngReturn As Integer = NetLocalGroupGetInfo("\\" & MachineName, AccountName, 0, bufPtr) 
     Call NetApiBufferFree(bufPtr) 
     bufPtr = IntPtr.Zero 
     If lngReturn = 0 Then 
      returnValue = "True" 
     Else 
      lngReturn = NetUserGetInfo("\\" & MachineName, AccountName, 0, bufPtr) 
      Call NetApiBufferFree(bufPtr) 
      bufPtr = IntPtr.Zero 
      If lngReturn = 0 Then 
       returnValue = "False" 
      End If 
     End If 
     Return returnValue 
    End Function 
End Class 
2

我遇到了同樣的問題,你有。在做了一些研究之後,我終於找到了一個體面的解決方案來解決這個問題:這個想法是使用WinAPI LookupAccountSid。 我已經對域名和本地帳戶進行了測試。 Domain \ User,NT Authority \ System,MachineName \ Administrators將全部工作。 請注意,我不會在那裏放置任何異常處理。你可以判斷你的場景可以接受什麼樣的處理。要得到例外,您可以使用System.Runtime.InteropServices.Marshal.GetLastWin32Error()

public enum PrincipalType 
{ 
    User, 
    Group 
} 
public bool TryGetPrincipalType(string domainQualifiedName, out PrincipalType type) 
{ 
     var name = new StringBuilder(); 
     var cchName = (uint) name.Capacity; 
     var referencedDomainName = new StringBuilder(); 
     var cchReferencedDomainName = (uint) referencedDomainName.Capacity; 
     SID_NAME_USE sidType; 

     var account = new NTAccount(domainQualifiedName); 

     var id = new SecurityIdentifier(account.Translate(typeof (SecurityIdentifier)).Value); 
     var sidBuffer = new byte[id.BinaryLength]; 
     id.GetBinaryForm(sidBuffer, 0); 

     if (LookupAccountSid(null, sidBuffer, name, ref cchName, referencedDomainName, 
          ref cchReferencedDomainName, out sidType)) 
     { 
      switch (sidType) 
      { 
       case SID_NAME_USE.SidTypeGroup: 
       case SID_NAME_USE.SidTypeWellKnownGroup: 
       case SID_NAME_USE.SidTypeAlias: 
        type = PrincipalType.Group; 
        return true; 
       case SID_NAME_USE.SidTypeUser: 
        type = PrincipalType.User; 
        return true; 
      } 
     } 
     type = default(PrincipalType); 
     return false; 
    } 
private enum SID_NAME_USE 
{ 
    SidTypeUser = 1, 
    SidTypeGroup, 
    SidTypeDomain, 
    SidTypeAlias, 
    SidTypeWellKnownGroup, 
    SidTypeDeletedAccount, 
    SidTypeInvalid, 
    SidTypeUnknown, 
    SidTypeComputer 
} 
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
private static extern bool LookupAccountSid(
     string lpSystemName, 
     [MarshalAs(UnmanagedType.LPArray)] byte[] Sid, 
     StringBuilder lpName, 
     ref uint cchName, 
     StringBuilder ReferencedDomainName, 
     ref uint cchReferencedDomainName, 
     out SID_NAME_USE peUse);