简体   繁体   English

如何提高用户层次结构的 LDAP 搜索过滤器的性能

[英]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

  • Output will include all Level 0 reports below Level 1 User(input CN)输出将包括低于 1 级用户的所有 0 级报告(输入 CN)

IF input CN is Level 2 users CN中频输入CN为2级用户CN

  • Output will include all Level 1 and Level 2 reports below Level 1 User(input CN) ... and so on输出将包括所有低于 1 级用户(输入 CN)的 1 级和 2 级报告......等等

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属性,则应按以下步骤操作:

  1. Retrieve the specified user object and retrieve the directReports attribute检索指定的用户对象并检索directReports属性
  2. for every value of directReports that is returned, read the user object it points to, and retrieve their directReports attribute对于返回的每个directReports值,读取它指向的用户对象,并检索它们的directReports属性
  3. Repeat step 2 for every value of directReportsdirectReports每个值重复步骤 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.您必须搜索将给定用户作为管理员的用户。

  1. Retrieve the specified user object and get the DN (via SearchResult.getNameInNameSpace()检索指定的用户对象并获取 DN(通过SearchResult.getNameInNameSpace()
  2. search for users with (manager=<DN>) where <DN> is the one you just resolved搜索具有(manager=<DN>)用户,其中<DN>是您刚刚解析的用户
  3. for each result, get the DN and repeat step 2对于每个结果,获取 DN 并重复步骤 2

If you store each user while iterating, you will end up with the required list.如果您在迭代时存储每个用户,您将得到所需的列表。

Some more pointers:还有一些提示:

  • in your 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)。
  • searching for (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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM