Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何克服;成员';“无法解析s SID”;检查用户是否为组成员时出错?_C#_Active Directory - Fatal编程技术网

C# 如何克服;成员';“无法解析s SID”;检查用户是否为组成员时出错?

C# 如何克服;成员';“无法解析s SID”;检查用户是否为组成员时出错?,c#,active-directory,C#,Active Directory,我们有一个流程,需要检查特定用户是否是本地Administrators组的成员 检查的代码如下所示: using (PrincipalContext context = new PrincipalContext(ContextType.Machine, null)) { UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, sUserName); if (us

我们有一个流程,需要检查特定用户是否是本地Administrators组的成员

检查的代码如下所示:

using (PrincipalContext context = new PrincipalContext(ContextType.Machine, null))
{
    UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, sUserName);
    if (user != null)
    {
         SecurityIdentifier adminsGroupSID = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
         GroupPrincipal group = GroupPrincipal.FindByIdentity(context, IdentityType.Sid, adminsGroupSID.Value);
         if (group != null)
         {
             if (user.IsMemberOf(group))
                 return 0;
         }
    }
}
当组中有已删除的帐户(例如域帐户)时,我们将收到PrincipalOperationException和消息“枚举组成员身份时出错(1332)。无法解析成员的SID。”

有没有办法克服这一问题而不: a) 从组中手动删除孤立的SID b) 不忽视它


谢谢

有三种可能的解决方案(均未经测试,将最后一种方案用于所有类型的域组):
1) 加载组并自己枚举成员
2) 加载组的基础对象并使用属性[“Members”],这是一个SID列表。

3) 使用用户的GetAuthorizationGroups()(也将使用您的非直接组,服务帐户最终必须是“Windows授权组”和“PreWindows 2000 Comaptable…”的成员)并使用组列表查找您的管理组。

避免错误的一种方法是使用其他方法。 首先检索所有组并检查目标组的列表,而不是检查用户是否是组的成员。一个缺点是:速度较慢

var groups = UserPrincipal.Current.GetAuthorizationGroups();
var found = groups.FirstOrDefault(principal => principal.Name == "Administrators");
var isMemberOfAdminGroup = found != null;

谢谢你的帮助:)

这主要是基于我在迈克尔·塞勒(Michael Seier)的著作中的发现。他试图获取本地管理员帐户的SID,而我们只需要该组中的名称。“无法解析成员的SID”错误的原因是,Active Directory中有一些帐户已无法识别,很可能是指向已删除用户帐户的遗迹。你可以按照微软的说法删除它们,希望你的应用不会再次崩溃(尽管下次删除管理员组中的帐户时会崩溃),也可以使用Mike略微修改的代码永久解决问题

using System.DirectoryServices;
using System.Collections;
using System.Runtime.InteropServices;

[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);

private static string GetTextualSID(DirectoryEntry objGroup)
{
    string sSID = string.Empty;
    byte[] SID = objGroup.Properties["objectSID"].Value as byte[];
    IntPtr sidPtr = Marshal.AllocHGlobal(SID.Length);
    sSID = "";
    System.Runtime.InteropServices.Marshal.Copy(SID, 0, sidPtr, SID.Length);
    ConvertSidToStringSid((IntPtr)sidPtr, out sSID);
    System.Runtime.InteropServices.Marshal.FreeHGlobal(sidPtr);
    return sSID; 
}


public static List<string> GetLocalAdministratorsNames()
{
    List<string> admins = new List<string>();
    DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + Environment.MachineName);
    string adminsSID = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null).ToString();

    string localizedAdmin = new System.Security.Principal.SecurityIdentifier(adminsSID).Translate(typeof(System.Security.Principal.NTAccount)).ToString();

    localizedAdmin = localizedAdmin.Replace(@"BUILTIN\", "");

    DirectoryEntry admGroup = localMachine.Children.Find(localizedAdmin, "group");
    object adminmembers = admGroup.Invoke("members", null);

    DirectoryEntry userGroup = localMachine.Children.Find("users", "group");
    object usermembers = userGroup.Invoke("members", null);

    //Retrieve each user name.
    foreach (object groupMember in (IEnumerable)adminmembers)
    {
        DirectoryEntry member = new DirectoryEntry(groupMember);

        string sidAsText = GetTextualSID(member);
        admins.Add(member.Name);            
    }
    return admins;
}

谢谢你的回复。我会检查能做什么。另外,您可能会推荐一些类似的解决方案来将用户添加到组中?在执行group.Members.Add(user)时也会遇到同样的问题。好吧,底层对象将始终工作,但不如AccountManagement命名空间那么舒适。但是AccountManagement名称空间似乎有一些缺陷,需要解决。你也可以为这些组编写一个修复函数…@TGlatzer:我如何枚举?我在循环时出错了。1.无法列举。正如Rajesh所展示的,它给出了一个例外——微软甚至不在乎修复它,因为他们说解决办法是删除死掉的帐户。2. <加载
DirectoryEntry de=(DirectoryEntry)groupPrincipal.GetUnderlyingObject()时,code>GetUnderlyingObject()未提供任何值。3.  
GetAuthorizationGroups()
不利于AD,而不是本地计算机或其他远程计算机。它是以广告为中心的,与本地组无关。如果要检查计算机上的本地Administrators组,这将没有帮助。这将在AD中查询Administrators组-这样我们就清楚了。
GetAuthorizationGroups()
不符合AD,而不是本地计算机或其他远程计算机。它以广告为中心,与当地团体无关。也就是说,使用内置组的SID查看该组是否在AD管理员组中有点奇怪,但可能会起作用。我没有测试这个,但这有点像是先在谷仓里转一圈,而不是直接进门。
private static bool isAdmin(string user)
{
    //string user = @"DOMAIN\doej";
    user = user.Split(@'\')[1];

    List<string> admins = GetLocalAdministratorsNames();
    foreach (string s in admins)
    {
        if (s == user)
            return true; // admin found
    }
    return false;  // not an admin
}
public static bool UserHasLocalAdminPrivledges(this UserPrincipal up)
{
   SecurityIdentifier id = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
   return up.GetAuthorizationGroups().Any(g => g.Sid == id)
}