[英]How to improve performance of LDAP Search Filter for User Hierarchy
I want to search the Reporting hierarchy of a given CN and by using Manager attributes, in a downward direction in LDAP.我想在 LDAP 中向下搜索给定 CN 的报告层次结构并使用管理器属性。 Can anyone help us to know if there is any performant way of achieving this with the LDAP Search filters in Java?
任何人都可以帮助我们知道是否有任何高效的方法可以使用 Java 中的 LDAP 搜索过滤器来实现这一点? I tried searching different posts but couldn't find an answer.
我尝试搜索不同的帖子,但找不到答案。
Ex:
-Dept Head(input CN) - -Level 3 User
--Manager 1 -Level 2 User
---Member 1 -Level 1 User
---Member 2 -Level 1 User
--Manager 2 -Level 2 User
---Member 3 -Level 1 User
---Member 4 -Level 1 User
--Manager 3 -Level 2 User
---Member 5 -Level 1 User
---Member 6 -Level 1 User
In the above example Level 3 Users CN would be input and we should retrieve all the users below him till Level 0(all level Managers and Members) of the given CN.在上面的示例中,将输入级别 3 用户 CN,我们应该检索他下面的所有用户,直到给定 CN 的级别 0(所有级别的经理和成员)。
IF input CN is Level 1 users CN IF输入CN为1级用户CN
IF input CN is Level 2 users CN中频输入CN为2级用户CN
Right now I am generating a filter for each level dynamically and searching using that filter in the below level.现在我正在为每个级别动态生成一个过滤器,并在下面的级别中使用该过滤器进行搜索。 If there are more levels, the search is taking time to return the expected results.
如果有更多级别,则搜索需要时间才能返回预期结果。
My Code我的代码
protected static ArrayList<ValueCollection> getUserReportsTreeDetails(String accountName, String initial,
String url, String principal, String credentials, String searchFeilds, String resultFeildNames,
String managerAttribute) throws Exception {
InitialLdapContext adminContext = null;
try {
ArrayList<SearchResult> result = new ArrayList<SearchResult>();
Properties connectionProperties = new Properties();
connectionProperties.put("java.naming.factory.initial", initial);
connectionProperties.put("java.naming.provider.url", url);
connectionProperties.put("java.naming.referral", "ignore");
connectionProperties.put("java.naming.security.principal", principal);
connectionProperties.put("java.naming.security.credentials", credentials);
connectionProperties.put("javax.security.sasl.maxbuffer", 2000000);
adminContext = new InitialLdapContext(connectionProperties, null);
String filter;
filter = "(&(userstatus=active)(|(" + managerAttribute + "=" + accountName + ")(CN=" + accountName + ")))";
String searchFeildsArray[] = searchFeilds.split(",");
String resultFeildNamesArray[] = resultFeildNames.split(",");
NamingEnumeration<SearchResult> answers = null;
//
ArrayList<ValueCollection> values = new ArrayList<ValueCollection>();
try {
String baseDn = "ou=accounts"; // TODO: Change me
answers = adminContext.search(baseDn, filter, getSearchControlsForFetchUser(searchFeilds));
SearchResult userInfo;
if (!answers.hasMore()) {
// throw new Exception("User does not exist in AD");
return null;
}
try {
String Names = "";
int count = 0;
while (answers.hasMore()) {
ValueCollection data = new ValueCollection();
userInfo = (SearchResult) answers.next();
for (int i = 0; i < searchFeildsArray.length; i++) {
Attribute attr = userInfo.getAttributes().get(searchFeildsArray[i]);
if (attr != null) {
data.put(resultFeildNamesArray[i], new StringPrimitive(attr.get().toString()));
}
}
values.add(data);
String temp = userInfo.getAttributes().get("cn").get().toString();
if (!temp.equals(accountName)) {
Names = Names == "" ? temp : Names + "," + temp;
count++;
}
}
if (Names.length() > 0)
values = getData(Names, managerAttribute, adminContext, baseDn, searchFeilds, resultFeildNames,
values);
return values;
} catch (PartialResultException var10) {
throw new Exception("User does not exist in AD or credentials are invalid");
}
} finally {
if (answers != null) {
answers.close();
}
}
} finally {
if (adminContext != null) {
adminContext.close();
}
}
}
private static ArrayList<ValueCollection> getData(String accountNames, String managerAttribute,
InitialLdapContext adminContext, String baseDn, String searchFeilds, String resultFeildNames,
ArrayList<ValueCollection> values) throws Exception {
String filter = "";
String[] Names = accountNames.split(",");
filter = "(&(userstatus=active)(|";
for (String Name : Names) {
filter += "(" + managerAttribute + "=" + Name + ")";
}
filter += "))";
String searchFeildsArray[] = searchFeilds.split(",");
String resultFeildNamesArray[] = resultFeildNames.split(",");
NamingEnumeration<SearchResult> answers = null;
// String filter = "(" + managerAttribute + "=" + accountName + ")";
answers = adminContext.search(baseDn, filter, getSearchControlsForFetchUser(searchFeilds));
SearchResult userInfo;
String SearchedUsers = "";
int count = 0;
while (answers.hasMore()) {
ValueCollection data = new ValueCollection();
userInfo = (SearchResult) answers.next();
for (int i = 0; i < searchFeildsArray.length; i++) {
Attribute attr = userInfo.getAttributes().get(searchFeildsArray[i]);
if (attr != null) {
data.put(resultFeildNamesArray[i], new StringPrimitive(attr.get().toString()));
}
}
values.add(data);
String temp = userInfo.getAttributes().get("cn").get().toString();
SearchedUsers = SearchedUsers == "" ? temp : SearchedUsers + "," + temp;
count++;
}
if (SearchedUsers.length() > 0)
values = getData(SearchedUsers, managerAttribute, adminContext, baseDn, searchFeilds, resultFeildNames,
values);
return values;
}
Congratulations!恭喜! You are using the best LDAP server available.
您正在使用最好的 LDAP 服务器。
I assume the default attributes are used for the hierarchy: manager
for a person's manager and directReports
for their subordinates.我假设默认属性用于层次结构:
manager
代表一个人的经理, directReports
代表他们的下属。 These are DN attributes, meaning they point directly to an object and you can read them instead of searching for them.这些是DN属性,这意味着它们直接指向一个对象,您可以读取它们而不是搜索它们。
Case 1: directReports is available案例一:directReports可用
The directReports
attribute points downward in the organizational tree. directReports
属性在组织树中指向下方。 If the directReports
attribute is populated, you should proceed as follows:如果填充了
directReports
属性,则应按以下步骤操作:
directReports
attributedirectReports
属性directReports
that is returned, read the user object it points to, and retrieve their directReports
attributedirectReports
值,读取它指向的用户对象,并检索它们的directReports
属性directReports
directReports
每个值重复步骤 2 If you store each user while iterating, you will end up with the required list.如果您在迭代时存储每个用户,您将得到所需的列表。
Case 2: only manager is available情况 2:只有 manager 可用
This is a little more work.这是一个多一点的工作。 The
manager
attribute points upwards in the organizational tree. manager
属性在组织树中指向上方。 You will have to search for users that have the given user as manager.您必须搜索将给定用户作为管理员的用户。
SearchResult.getNameInNameSpace()
SearchResult.getNameInNameSpace()
(manager=<DN>)
where <DN>
is the one you just resolved(manager=<DN>)
用户,其中<DN>
是您刚刚解析的用户 If you store each user while iterating, you will end up with the required list.如果您在迭代时存储每个用户,您将得到所需的列表。
Some more pointers:还有一些提示:
adminContext.search()
the baseDN is either the value from directReports
(case 1) or the normal base DN (case 2).adminContext.search()
,baseDN 是来自directReports
的值(案例 1)或正常的基本 DN(案例 2)。(manager=<accountname>)
will not yield any results in your example because <accountname>
is not a DN value (like cn=accountname,ou=users,o=org )(manager=<accountname>)
不会产生任何结果,因为<accountname>
不是 DN 值(如cn=accountname,ou=users,o=org )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.