You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何从Active Directory获取自定义安全组

筛选AD中的自定义安全组

好问题!确实Active Directory里没有专门标记「自定义组」的内置属性,但我们可以通过组所在的OU/容器路径来间接实现筛选——毕竟系统默认的安全组基本都集中在Builtin、Users这些默认容器里,而你自己创建的组大概率会放在自定义OU下。

先提个小细节:你当前代码里的lstAdGroups.Items.Clear();是放在foreach循环内部的,这会导致每次循环都清空列表,最后只会显示最后一个找到的组,记得把它移到循环外面哦!

下面给你两种可行的实现方案:

方案一:用LDAP筛选器在AD服务器端过滤(效率更高)

这种方式直接在AD服务器上完成筛选,不用把所有组都拉到客户端再过滤,性能更好。核心思路是构造LDAP筛选条件,只返回安全组,且排除Builtin和Users容器下的组。

try {
    Logging.LogMessageToFile("Reading custom Security Groups from AD.");
    PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
    
    // 获取域的根DN,用来拼接默认容器的完整DN
    DirectoryEntry domainEntry = ctx.GetUnderlyingObject() as DirectoryEntry;
    string domainDN = domainEntry.Properties["distinguishedName"].Value.ToString();
    string usersContainerDN = $"CN=Users,{domainDN}";
    string builtinContainerDN = $"CN=Builtin,{domainDN}";

    // 构造LDAP筛选器:
    // - objectCategory=group:筛选组对象
    // - groupType:1.2.840.113556.1.4.803:=2:筛选安全组(位运算匹配groupType中的安全组标记)
    // - !distinguishedName=*{usersContainerDN}:排除Users容器下的组
    // - !distinguishedName=*{builtinContainerDN}:排除Builtin容器下的组
    string ldapFilter = $"(& (objectCategory=group) (groupType:1.2.840.113556.1.4.803:=2) (!distinguishedName=*{usersContainerDN}) (!distinguishedName=*{builtinContainerDN}) )";
    
    GroupPrincipal qbeGroup = new GroupPrincipal(ctx);
    qbeGroup.QueryFilter = new LDAPFilter(ldapFilter);
    
    PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);
    
    // 先清空列表,再批量添加符合条件的组
    lstAdGroups.Items.Clear();
    foreach (var found in srch.FindAll()) {
        lstAdGroups.Items.Add(found);
    }
} catch (Exception ex) {
    Logging.LogMessageToFile("Unexpected error reading custom Security Groups from AD: " + ex.Message);
}

方案二:客户端遍历结果时过滤(更直观)

如果不想写LDAP筛选器,也可以先获取所有安全组,再在客户端过滤掉默认容器下的组:

try {
    Logging.LogMessageToFile("Reading custom Security Groups from AD.");
    PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
    
    // 先筛选所有安全组
    GroupPrincipal qbeGroup = new GroupPrincipal(ctx);
    qbeGroup.SecurityGroup = true;
    PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);
    
    // 获取默认容器的完整DN
    DirectoryEntry domainEntry = ctx.GetUnderlyingObject() as DirectoryEntry;
    string domainDN = domainEntry.Properties["distinguishedName"].Value.ToString();
    string usersContainerDN = $"CN=Users,{domainDN}";
    string builtinContainerDN = $"CN=Builtin,{domainDN}";
    
    lstAdGroups.Items.Clear();
    foreach (GroupPrincipal found in srch.FindAll()) {
        // 检查组的DN是否以默认容器DN结尾,不是则添加到列表
        bool isInDefaultContainer = found.DistinguishedName.EndsWith(usersContainerDN, StringComparison.OrdinalIgnoreCase) 
                                || found.DistinguishedName.EndsWith(builtinContainerDN, StringComparison.OrdinalIgnoreCase);
        if (!isInDefaultContainer) {
            lstAdGroups.Items.Add(found);
        }
    }
} catch (Exception ex) {
    Logging.LogMessageToFile("Unexpected error reading custom Security Groups from AD: " + ex.Message);
}

额外说明

  • 如果你的环境中还有其他需要排除的默认容器(比如Domain Controllers下的系统组),可以用同样的方式添加到筛选条件中。
  • 极少数情况下,如果自定义组被误放在Users容器中,这种方法会把它排除。如果需要兼容这种场景,可以考虑结合组的创建时间辅助筛选(系统组的创建时间通常和域创建时间一致,自定义组是之后创建的),但这种方式不如OU路径筛选可靠,优先推荐前者。

内容的提问来源于stack exchange,提问作者Rawns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:52:27