如何检查NTAccount对象表示组还是用户?

5

当处理由

返回的访问规则时,

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

如何判断每个规则中引用的NTAccount对象是用户账户还是组?

更新:

我已经解决了这个问题。请注意,此代码的目的是在检查期间返回True(如果NTAccount是一个组),否则返回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 返回错误1722以获得更多详细信息。

2个回答

5

我遇到了你所遇到的问题。在到处进行研究后,我终于找到了一个不错的解决方案:使用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);

那么对于 Active Directory 中的 Group 呢?适用于 Domain\GroupName 吗? - Kiquenet

2
答案确实是使用Windows APIs(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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接