Java LDAP查询获取组的所有组(嵌套)

Java LDAP查询获取组的所有组(嵌套),java,active-directory,ldap,active-directory-group,Java,Active Directory,Ldap,Active Directory Group,我想列出Active Directory中的所有组,包括嵌套组 通过这一点,我得到了顶级团队: try { Hashtable<String,String> props = new Hashtable<String,String>(); props.put(Context.SECURITY_AUTHENTICATION, "simple"); props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.j

我想列出Active Directory中的所有组,包括嵌套组

通过这一点,我得到了顶级团队:

try {
    Hashtable<String,String> props = new Hashtable<String,String>();
    props.put(Context.SECURITY_AUTHENTICATION, "simple");
    props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    props.put(Context.PROVIDER_URL, "ldap://adserver");
    props.put(Context.SECURITY_PRINCIPAL, "user@domain");
    props.put(Context.SECURITY_CREDENTIALS, "password");

    DirContext ctx = new InitialDirContext(props);

    SearchControls cons = new SearchControls();
    cons.setReturningAttributes(new String[] {"cn"});
    cons.setSearchScope(SearchControls.ONELEVEL_SCOPE);

    NamingEnumeration<SearchResult> answer = ctx.search("cn=users,dc=domain,dc=com", "(objectcategory=group)", cons);
    System.out.println("AD GROUPS:");
    while(answer.hasMore()) {
        SearchResult result = (SearchResult) answer.next();
        Attributes atts = result.getAttributes();
        Attribute att = atts.get("cn");
        String groupName = (String)att.get();

        //how to search for groups nested in this group
    }
} catch (NamingException e) {
    e.printStackTrace();
}
试试看{
Hashtable props=新的Hashtable();
props.put(Context.SECURITY_认证,“simple”);
put(Context.INITIAL\u Context\u工厂,“com.sun.jndi.ldap.LdapCtxFactory”);
props.put(Context.PROVIDER\u URL,“ldap://adserver");
props.put(Context.SECURITY\u PRINCIPAL,“user@domain");
props.put(Context.SECURITY_凭证,“密码”);
DirContext ctx=新的初始DirContext(props);
SearchControls cons=新的SearchControls();
cons.SetReturningAttribute(新字符串[]{“cn”});
cons.设置搜索范围(搜索控制.一级搜索范围);
NamingEnumeration answer=ctx.search(“cn=users,dc=domain,dc=com”,“objectcategory=group)”,cons);
System.out.println(“广告组:”);
while(answer.hasMore()){
SearchResult=(SearchResult)answer.next();
Attributes atts=result.getAttributes();
属性att=atts.get(“cn”);
String groupName=(String)att.get();
//如何搜索嵌套在此组中的组
}
}捕获(NamingE例外){
e、 printStackTrace();
}
如何获取嵌套组?我在谷歌上搜索了一下,发现有两种方法:

NamingEnumeration<SearchResult> nested = ctx.search("cn=users,dc=domain,dc=com", "(&(objectClass=group)(objectCategory=group)(memberOf:1.2.840.113556.1.4.194:=cn="+groupName+"))", controls);
namingumeration nested=ctx.search(“cn=users,dc=domain,dc=com”,”(&(objectClass=group)(objectCategory=group)(memberOf:1.2.840.113556.1.4.194:=cn=“+groupName+”),控件);

namingumeration nested=ctx.search(“cn=users,dc=domain,dc=com”,”(&(objectClass=group)(objectCategory=group)(memberOf=cn=“+groupName+”),控件);

但这不会返回嵌套的组。我做错了什么?

您可以对类别使用过滤器,如下所示

(&(objectCategory=user)(memberOf=cn=MyCustomGroup,ou=ouOfGroup,dc=subdomain,dc=domain,dc=com))

您可以尝试下一步操作

Attribute memberOf = srLdapUser.getAttributes().get("memberOf");
if (memberOf != null) {
  for (int i = 0; i < memberOf.size(); i++) {
      Attributes atts = ctx.getAttributes(memberOf.get(i).toString(), new String[] { "CN" });
      Attribute att = atts.get("CN");
      groups.add((att.get().toString())); 
  }
  System.out.println(groups.toString());`
attributememberof=srLdapUser.getAttributes().get(“memberOf”);
if(memberOf!=null){
对于(int i=0;i
尝试更改

cons.setSearchScope(SearchControls.ONELEVEL_SCOPE); 


这应该允许您搜索下面的整个子树,包括您指定的级别,这对于Active Directory的memberOf:1.2.840.113556.1.4.1941很重要,如果您想查找嵌套组(不要替换此神奇的数字字符串)

这对我有用

(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941:=" + groupDn + "))

在LDAP中,我们可以查询用户是否属于给定的组。一旦您建立了连接,就可以使用member或memberOf属性进行查询

查询memberOf属性: 使用的筛选器:(&(组成员属性=组DN)(objectClass=组对象类))例如:(&(memberOf=CN=组,ou=qa_ou,dc=ppma,dc=org)(objectClass=组))

使用成员属性: 使用的筛选器:(&(组成员属性=用户DN)(对象类=组对象类))例如:(&(成员=CN=用户,ou=qa_ou,dc=ppma,dc=组织)(对象类=组))

但您必须使用用户的member或memberOf属性列表进行递归搜索。例如,如果用户具有以下组层次结构:

cn:user1成员:cn=group1,DC=foo,DC=example,DC=com成员:cn=group2,DC=foo,DC=example,DC=com

然后,您需要使用附加的LDAP搜索递归地查找group1和group2,依此类推,查找这些组所属的组

我们不能在生产中使用LDAP\u匹配\u规则\u,因为当我们有太深的嵌套层次结构时,它不起作用,并且只适用于Active Directory。下面的解决方案与AD或OpenLDAP独立工作,我们只需要替换组属性

下面是查询用户所属的所有嵌套组的示例代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class MemberDemo {
    private static final String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
    private static final String connectionURL = "ldap://10.224.243.133:389";
    private static final String connectionName = "CN=administrator,CN=users,DC=ppma,DC=org";
    private static final String connectionPassword = "Conleyqa12345";

    public static int nestLevel = 3;
    public static int level = 1;

    // Optional
    private static final String authentication = null;
    private static final String protocol = null;
    private static String userBase = "OU=qa_OU,DC=ppma,DC=org";

    public static void main(String[] args) throws NamingException {
        long start = System.currentTimeMillis();

        Hashtable<String, String> env = new Hashtable<String, String>();

        // Configure our directory context environment.

        env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
        env.put(Context.PROVIDER_URL, connectionURL);
        env.put(Context.SECURITY_PRINCIPAL, connectionName);
        env.put(Context.SECURITY_CREDENTIALS, connectionPassword);
        if (authentication != null)
            env.put(Context.SECURITY_AUTHENTICATION, authentication);
        if (protocol != null)
            env.put(Context.SECURITY_PROTOCOL, protocol);

        InitialDirContext context = new InitialDirContext(env);

        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

        Set<String> traversedGroups = new HashSet<String>();
        Set<String> relatedGroups = new HashSet<String>();
        List<String> tempParentColl = new CopyOnWriteArrayList<String>();
        List<String> tempGroups = new ArrayList<String>();

        String loginUser = "CN=qa20Nest,OU=qa_OU,DC=ppma,DC=org";

        String filter = "(&(member=" + loginUser + ")(objectClass=group))";
        tempGroups = findNestedGroups(tempGroups, context, filter, loginUser, constraints,
                tempParentColl, traversedGroups, getUserName(loginUser));
        relatedGroups.addAll(tempGroups);

        System.out.println("Parent Groups :");

        for (String group : relatedGroups) {
            System.out.println(group);
        }
        long end = System.currentTimeMillis();
        long elapsedTime = end - start;
        System.out.println("Total time taken in sec : " + elapsedTime / 1000);

    }

    @SuppressWarnings("rawtypes")
    public static List<String> findNestedGroups(List<String> tempGrpRelations, InitialDirContext context, String filter,
            String groupName, SearchControls constraints, List<String> tempParentColl, Set<String> traversedGrp,
            String groupIdentifier) {
        NamingEnumeration results;
        try {
            traversedGrp.add(groupName);
            results = context.search(userBase, filter, constraints);

            // Fail if no entries found
            if (results == null || !results.hasMore()) {
                System.out.println("No result found for :" + groupName);
                if (tempParentColl.isEmpty()) {
                    return tempGrpRelations;
                } else {
                    tempParentColl.remove(groupName);
                }
            }

            while (results.hasMore()) {
                SearchResult result = (SearchResult) results.next();
                System.out.println("DN - " + result.getNameInNamespace());
                tempParentColl.add(result.getNameInNamespace());
                tempGrpRelations.add(result.getNameInNamespace());
            }

            Iterator<String> itr = tempParentColl.iterator();
            while (itr.hasNext()) {
                String groupDn = itr.next();
                String nfilter = "(&(member=" + groupDn + ")(objectClass=group))";
                tempParentColl.remove(groupDn);
                if (!traversedGrp.contains(groupDn)) {
                    findNestedGroups(tempGrpRelations, context, nfilter, groupDn, constraints, tempParentColl,
                            traversedGrp, getUserName(groupDn));
                }
            }

        } catch (NamingException e) {
            e.printStackTrace();
        }
        return tempGrpRelations;
    }

    public static String getUserName(String cnName) {

        String name = cnName.substring(cnName.indexOf("CN=")).split(",")[0].split("=")[1];
        return name;
    }
}
import java.util.ArrayList;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.Hashtable;
导入java.util.Iterator;
导入java.util.List;
导入java.util.Map;
导入java.util.Set;
导入java.util.concurrent.CopyOnWriteArrayList;
导入javax.naming.Context;
导入javax.naming.NamingEnumeration;
导入javax.naming.NamingException;
导入javax.naming.directory.InitialDirContext;
导入javax.naming.directory.SearchControls;
导入javax.naming.directory.SearchResult;
公共类成员演示{
私有静态最终字符串contextFactory=“com.sun.jndi.ldap.LdapCtxFactory”;
专用静态最终字符串connectionURL=”ldap://10.224.243.133:389";
私有静态最终字符串connectionName=“CN=administrator,CN=users,DC=ppma,DC=org”;
私有静态最终字符串连接password=“Conleyqa12345”;
公共静态int nestLevel=3;
公共静态int级别=1;
//可选的
私有静态最终字符串身份验证=null;
私有静态最终字符串协议=null;
私有静态字符串userBase=“OU=qa\u OU,DC=ppma,DC=org”;
公共静态void main(字符串[]args)引发NamingException{
长启动=System.currentTimeMillis();
Hashtable env=新的Hashtable();
//配置目录上下文环境。
环境放置(Context.INITIAL\u Context\u FACTORY,contextFactory);
env.put(Context.PROVIDER\uURL,connectionURL);
环境put(Context.SECURITY\u主体,connectionName);
环境放置(Context.SECURITY\u凭证、连接密码);
if(身份验证!=null)
环境put(Context.SECURITY\u身份验证、身份验证);
if(协议!=null)
环境put(Context.SECURITY_协议,协议);
InitialDirContext=新的InitialDirContext(env);
SearchControls约束=新的SearchControls();
约束.setSearchScope(SearchControls.SUBTREE_范围);
Set traversedGroups=new HashSet();
Set relatedGroups=new HashSet();
列表tempParentColl=新副本
(&(objectCategory=Person)(sAMAccountName=*)(memberOf:1.2.840.113556.1.4.1941:=CN=Test group,CN=Users,DC=domain,DC=net))
(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941:=" + groupDn + "))
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class MemberDemo {
    private static final String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
    private static final String connectionURL = "ldap://10.224.243.133:389";
    private static final String connectionName = "CN=administrator,CN=users,DC=ppma,DC=org";
    private static final String connectionPassword = "Conleyqa12345";

    public static int nestLevel = 3;
    public static int level = 1;

    // Optional
    private static final String authentication = null;
    private static final String protocol = null;
    private static String userBase = "OU=qa_OU,DC=ppma,DC=org";

    public static void main(String[] args) throws NamingException {
        long start = System.currentTimeMillis();

        Hashtable<String, String> env = new Hashtable<String, String>();

        // Configure our directory context environment.

        env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
        env.put(Context.PROVIDER_URL, connectionURL);
        env.put(Context.SECURITY_PRINCIPAL, connectionName);
        env.put(Context.SECURITY_CREDENTIALS, connectionPassword);
        if (authentication != null)
            env.put(Context.SECURITY_AUTHENTICATION, authentication);
        if (protocol != null)
            env.put(Context.SECURITY_PROTOCOL, protocol);

        InitialDirContext context = new InitialDirContext(env);

        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

        Set<String> traversedGroups = new HashSet<String>();
        Set<String> relatedGroups = new HashSet<String>();
        List<String> tempParentColl = new CopyOnWriteArrayList<String>();
        List<String> tempGroups = new ArrayList<String>();

        String loginUser = "CN=qa20Nest,OU=qa_OU,DC=ppma,DC=org";

        String filter = "(&(member=" + loginUser + ")(objectClass=group))";
        tempGroups = findNestedGroups(tempGroups, context, filter, loginUser, constraints,
                tempParentColl, traversedGroups, getUserName(loginUser));
        relatedGroups.addAll(tempGroups);

        System.out.println("Parent Groups :");

        for (String group : relatedGroups) {
            System.out.println(group);
        }
        long end = System.currentTimeMillis();
        long elapsedTime = end - start;
        System.out.println("Total time taken in sec : " + elapsedTime / 1000);

    }

    @SuppressWarnings("rawtypes")
    public static List<String> findNestedGroups(List<String> tempGrpRelations, InitialDirContext context, String filter,
            String groupName, SearchControls constraints, List<String> tempParentColl, Set<String> traversedGrp,
            String groupIdentifier) {
        NamingEnumeration results;
        try {
            traversedGrp.add(groupName);
            results = context.search(userBase, filter, constraints);

            // Fail if no entries found
            if (results == null || !results.hasMore()) {
                System.out.println("No result found for :" + groupName);
                if (tempParentColl.isEmpty()) {
                    return tempGrpRelations;
                } else {
                    tempParentColl.remove(groupName);
                }
            }

            while (results.hasMore()) {
                SearchResult result = (SearchResult) results.next();
                System.out.println("DN - " + result.getNameInNamespace());
                tempParentColl.add(result.getNameInNamespace());
                tempGrpRelations.add(result.getNameInNamespace());
            }

            Iterator<String> itr = tempParentColl.iterator();
            while (itr.hasNext()) {
                String groupDn = itr.next();
                String nfilter = "(&(member=" + groupDn + ")(objectClass=group))";
                tempParentColl.remove(groupDn);
                if (!traversedGrp.contains(groupDn)) {
                    findNestedGroups(tempGrpRelations, context, nfilter, groupDn, constraints, tempParentColl,
                            traversedGrp, getUserName(groupDn));
                }
            }

        } catch (NamingException e) {
            e.printStackTrace();
        }
        return tempGrpRelations;
    }

    public static String getUserName(String cnName) {

        String name = cnName.substring(cnName.indexOf("CN=")).split(",")[0].split("=")[1];
        return name;
    }
}