5 Stimmen

Wie prüfe ich, ob ein NTAccount-Objekt eine Gruppe oder einen Benutzer darstellt?

Bei der Arbeit mit den Zugriffsregeln, die von

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

Wie kann ich feststellen, ob das NTAccount-Objekt, auf das in jeder Regel verwiesen wird, ein Benutzerkonto oder eine Gruppe ist?

Aktualisierung:

Ich konnte das Problem wie folgt lösen. Beachten Sie, dass der Zweck dieses Codes darin besteht, Folgendes zurückzugeben True wenn die NTAccount ist eine Gruppe, und False andernfalls oder wenn bei der Prüfung ein Fehler auftritt.

Gibt es eine bessere Möglichkeit, dies zu tun?

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

Ein weiteres Update:

Die obige Lösung war für die meisten Server ausreichend \account Objekte, aber es schlägt bei lokalen Gruppenobjekten auf den EMC Celerra NAS-Servern, die wir haben, fehl. Ich versuche, die Win-API-Aufrufe NetUserGetInfo/NetLocalGroupGetInfo zu verwenden, um zu sehen, ob das funktioniert, aber ich kann sie nicht richtig zum Laufen bringen. Siehe NetUserGetInfo/NetLocalGroupGetInfo liefert Fehler 1722 für weitere Einzelheiten.

5voto

Terry Tsay Punkte 161

Ich bin auf das gleiche Problem gestoßen, das Sie haben. Nach einigen Recherchen überall fand ich schließlich eine anständige Lösung, um dieses Problem zu lösen: Die Idee ist, WinAPI LookupAccountSid zu verwenden. Ich habe dies sowohl mit Domänen- als auch mit lokalen Konten getestet. Domäne \User NT-Behörde \System , Maschinenname \Administrators werden alle funktionieren. Beachten Sie, dass ich dort keine Ausnahmebehandlung einfüge. Sie können beurteilen, welche Art von Behandlung für Ihr Szenario akzeptabel ist. Um die Ausnahme zu erhalten, können Sie System.Runtime.InteropServices.Marshal.GetLastWin32Error() verwenden

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);

2voto

Andrew Cooper Punkte 31583

Die Antwort auf diese Frage war in der Tat die Verwendung der Windows-APIs ( NetUserGetInfo et NetLocalGroupGetInfo ).

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X