And*_*per 5 .net security pinvoke winapi
使用由返回的访问规则时
GetAccessRules(True, True, GetType(System.Security.Principal.NTAccount))
Run Code Online (Sandbox Code Playgroud)
如何判断每个规则中引用的NTAccount对象是用户帐户还是组?
更新:
我能够解决以下问题。请注意,此代码的目的是True如果s 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
Run Code Online (Sandbox Code Playgroud)
另一个更新:
对于大多数服务器\帐户对象来说,上述解决方案都可以,但对于我们拥有的EMC Celerra NAS服务器上的本地组对象,则无法解决。我正在尝试使用NetUserGetInfo / NetLocalGroupGetInfo Win API调用来查看是否可以运行,但是无法使其正常运行。有关更多详细信息,请参见NetUserGetInfo / NetLocalGroupGetInfo返回错误1722。
小智 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);
Run Code Online (Sandbox Code Playgroud)
答案确实是使用 Windows API(NetUserGetInfo和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
Run Code Online (Sandbox Code Playgroud)