我想列出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();
}
如何获取嵌套组?我用Google搜索了一下,发现了这两种方式:
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);
和
NamingEnumeration<SearchResult> nested = ctx.search("cn=users,dc=domain,dc=com", "(&(objectClass=group)(objectCategory=group)(memberOf=CN="+groupName+"))", controls);
但这不会返回嵌套组。我做错了什么?
答案 0 :(得分:1)
您可以尝试下一步
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());`
答案 1 :(得分:1)
如果要查找嵌套组,请使用memberOf:1.2.840.113556.1.4.1941对Active Directory很重要(不要替换此魔术数字字符串)。
(&(objectCategory=Person)(sAMAccountName=*)(memberOf:1.2.840.113556.1.4.1941:=CN=Test group,CN=Users,DC=domain,DC=net))
答案 2 :(得分:0)
您可以按类别使用过滤器
(及(objectCategory =用户)(=的memberOf CN = MyCustomGroup,OU = ouOfGroup,DC =子域,DC =域,DC = COM))
答案 3 :(得分:0)
这对我有用。
(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941:=" + groupDn + "))
答案 4 :(得分:0)
在 LDAP 中,我们可以在建立连接后查询用户是否属于给定组,您可以使用 member 或 memberOf 属性进行查询。
查询 memberOf 属性: 使用的过滤器:(&(Group Member Attribute=Group DN)(objectClass=Group Object class)) 例如:(&(memberOf=CN=group,ou=qa_ou,dc=ppma,dc=org)(objectClass=group))
使用成员属性: 使用的过滤器:(&(Group Member Attribute=User DN)(objectClass=Group Object class)) 例如:(&(member=CN=user,ou=qa_ou,dc=ppma,dc=org)(objectClass=group))
但是您必须使用用户的 member 或 memberOf 属性列表进行递归搜索。例如如果用户具有以下组层次结构:
cn: user1 memberOf: CN=group1,DC=foo,DC=example,DC=com memberOf: CN=group2,DC=foo,DC=example,DC=com
然后,您需要使用额外的 LDAP 搜索递归查找 group1 和 group2,对这些组所属的组依此类推。
我们不能在生产中使用 LDAP_MATCHING_RULE_IN_CHAIN,因为当嵌套层次太深时它不起作用,并且它只适用于 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;
}
}
答案 5 :(得分:-1)
尝试更改
cons.setSearchScope(SearchControls.ONELEVEL_SCOPE);
到
cons.setSearchScope(SearchControls.SUBTREE_SCOPE);
这应该允许您搜索下面的整个子树,包括您指定的级别