LDAP: как вернуть более 1000 результатов (java)

Я использую LDAP SDK с этого сайта: https://www.unboundid.com/products/ldap-sdk/< /а> . Я хотел бы сделать операцию поиска, которая возвращает много записей.

Согласно сайту часто задаваемых вопросов, ( https://www.unboundid.com/products/ldap-sdk/docs/ldapsdk-faq.php#search ) я должен использовать реализацию SearchResultListener.

Итак, вот что я сделал:

 public class UpdateThread extends Thread implements SearchResultListener {
 ...
 // create request
 final SearchRequest request = new SearchRequest(this, instance.getBaseDN(),SearchScope.SUB, filter);
 // Setting size limit of results.
 request.setSizeLimit(2000);

 ...

 // Get every result one by one.
 @Override
public void searchEntryReturned(SearchResultEntry arg0) {
    System.out.println("entry "+arg0.getDN());

}

Проблема в том, что "searchEntryReturned" возвращает максимум 1000 результатов. Даже если я установлю ограничение размера на «2000».


person stage    schedule 03.07.2012    source источник


Ответы (4)


Хотя почти наверняка сервер применяет ограничение размера в 1000 записей, потенциально существуют способы обойти это, отправив запрос в несколько частей.

Если сервер поддерживает использование простого постраничного управления результатами (как определено в RFC 2696 и поддерживается в LDAP SDK в соответствии с https://docs.ldap.com/ldap-sdk/docs/javadoc/com/unboundid/ldap/sdk/controls/SimplePagedResultsControl.html), то вы можете использовать его для перебора результатов на «страницах», содержащих указанное количество записей.

В качестве альтернативы, управление запросом представления виртуального списка (VLV) (https://www.unboundid.com/products/ldap-sdk/docs/javadoc/index.html?com/unboundid/ldap/sdk/controls/VirtualListViewRequestControl.html) можно было бы использовать, но я, вероятно, рекомендовал бы это только в том случае, если сервер не поддерживает простое управление результатами с разбивкой по страницам, потому что управление запросами VLV также требует сортировки результатов и, вероятно, требует специальной настройки на сервере. или какая-то довольно дорогая обработка, чтобы иметь возможность обслуживать запрос.

person Neil Wilson    schedule 03.07.2012

Довольно просто реализовать выгружаемый запрос LDAP с использованием стандартной Java, добавив PagedResultsControl к LdapContext, без использования стороннего API, как указано в ответе Нила выше.

Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env
    .put(Context.INITIAL_CONTEXT_FACTORY,
        "com.sun.jndi.ldap.LdapCtxFactory");

/* Specify host and port to use for directory service */
env.put(Context.PROVIDER_URL,
    "ldap://localhost:389/ou=People,o=JNDITutorial");

try {
  LdapContext ctx = new InitialLdapContext(env, null);

  // Activate paged results
  int pageSize = 5;
  byte[] cookie = null;
  ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize,
      Control.NONCRITICAL) });
  int total;

  do {
    /* perform the search */
    NamingEnumeration results = ctx.search("", "(objectclass=*)",
        new SearchControls());

    /* for each entry print out name + all attrs and values */
    while (results != null && results.hasMore()) {
      SearchResult entry = (SearchResult) results.next();
      System.out.println(entry.getName());
    }

    // Examine the paged results control response
    Control[] controls = ctx.getResponseControls();
    if (controls != null) {
      for (int i = 0; i < controls.length; i++) {
        if (controls[i] instanceof PagedResultsResponseControl) {
          PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
          total = prrc.getResultSize();
          if (total != 0) {
            System.out.println("***************** END-OF-PAGE "
                + "(total : " + total + ") *****************\n");
          } else {
            System.out.println("***************** END-OF-PAGE "
                + "(total: unknown) ***************\n");
          }
          cookie = prrc.getCookie();
        }
      }
    } else {
      System.out.println("No controls were sent from the server");
    }
    // Re-activate paged results
    ctx.setRequestControls(new Control[] { new PagedResultsControl(
        pageSize, cookie, Control.CRITICAL) });

  } while (cookie != null);

  ctx.close();

Пример скопирован из здесь.

person PeterK    schedule 31.07.2015

Я решил как @PeterK , но с некоторыми изменениями

    public List<MyUser> listUsers() {
    LOG.info("listUsers() inicio");
    List<MyUser> users = new ArrayList<MyUser>();

    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CTX);
    env.put(Context.PROVIDER_URL, 'ldap://192.168.10.10:389');
    env.put(Context.SECURITY_AUTHENTICATION, CONNECTION_TYPE);
    env.put(Context.SECURITY_PRINCIPAL, USER_ADMIN_PASSWORD);
    env.put(Context.SECURITY_CREDENTIALS, USER_ADMIN);

    try {
        LdapContext ctx = new InitialLdapContext(env, null);

        // Activate paged results
        int pageSize = 1000;
        byte[] cookie = null;
        ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, Control.NONCRITICAL) });
        int total;

        do {
            /* perform the search */
            SearchControls sc = new SearchControls();
            sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String filtro = "(&(sAMAccountName=*)&(objectClass=user))";
            NamingEnumeration results = ctx.search(getBaseDn(ctx), filtro, sc);

            /* for each entry */
            while (results.hasMoreElements()) {
                SearchResult result = (SearchResult) results.nextElement();
                Attributes attributes = result.getAttributes();
                //convert to MyUser class
                MyUser user = toUser(attributes);
                users.add(user);
            }

            // Examine the paged results control response
            Control[] controls = ctx.getResponseControls();
            if (controls != null) {
                for (int i = 0; i < controls.length; i++) {
                    if (controls[i] instanceof PagedResultsResponseControl) {
                        PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                        total = prrc.getResultSize();
                        if (total != 0) {
                            System.out.println("***************** END-OF-PAGE " + "(total : " + total + ") *****************\n");
                        } else {
                            System.out.println("***************** END-OF-PAGE " + "(total: unknown) ***************\n");
                        }
                        cookie = prrc.getCookie();
                    }
                }
            } else {
                System.out.println("No controls were sent from the server");
            }
            // Re-activate paged results
            ctx.setRequestControls(new Control[] { new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });

        } while (cookie != null);

        ctx.close();

    } catch (NamingException e) {
        System.err.println("PagedSearch failed.");
        e.printStackTrace();
    } catch (IOException ie) {
        System.err.println("PagedSearch failed.");
        ie.printStackTrace();
    } catch (Exception ie) {
        System.err.println("PagedSearch failed.");
        ie.printStackTrace();
    }

    LOG.info("listUsers() size = " + (users.size()));
    LOG.info("listUsers() fim");

    return users;
}


private MyUser toUser(Attributes attributes) throws NamingException {
    if (attributes != null) {
        String fullName = attributes.get("distinguishedName") != null ? attributes.get("distinguishedName").get().toString() : null;
        String mail = attributes.get("mail") != null ? attributes.get("mail").get().toString() : null;
        String userName = attributes.get("cn") != null ? attributes.get("cn").get().toString() : null;
        String userPrincipalName = attributes.get("userPrincipalName") != null ? attributes.get("userPrincipalName").get().toString() : null;

        if (userPrincipalName != null) {
            String[] user = userPrincipalName.split("@");
            if (user != null && user.length > 0) {
                userName = user[0];
            }
        }

        MyUser user = new MyUser();
        user.setFullName(fullName);
        user.setEmail(mail);
        user.setName(userName);
        user.setUserPrincipalName(userPrincipalName);
        user.setRoles(getRolesUser(attributes));

        return user;
    }

    return null;
}
person Joander Vieira Cândido    schedule 08.01.2016
comment
PeterK никогда не увидит ваше сообщение в том виде, в котором вы его видели - person Drew; 08.01.2016
comment
вы бы ввели комментарий под его ответом. Помните: под вашим ответом следующие люди получают предупреждение, когда вы публикуете комментарий под своим ответом ... (1) Оп, я думаю, но не держите меня за это, (2) другой комментатор, такой как я, если этот человек является единственным человек с веткой комментариев, как никто другой, который комментирует, (3) кто-то, кого вы @theirName, который уже находится под вашим ответом в комментарии или Op - person Drew; 09.01.2016
comment
Только потому, что (2) был случай выше, я был предупрежден, что вы написали этот комментарий выше. Как это сделать? ... в противном случае, если бы прокомментировал кто-то третий, я бы не был предупрежден. Многие люди думают, что их игнорируют в комментариях к SO, но на самом деле они понятия не имеют, что с ними разговаривают из-за того, как это работает. - person Drew; 09.01.2016
comment
Спасибо @Drew, но мой опубликованный выше код не помещается в поле для комментариев. - person Joander Vieira Cândido; 11.01.2016
comment
Я слышу тебя. Кажется, у вас есть хороший ответ выше. Я просто предупреждал вас о реальности того, как люди пингуются - person Drew; 11.01.2016
comment
Это очень медленно - person fatherazrael; 31.10.2019

Клиент LDAP устанавливает ограничение размера, запрашиваемое клиентом, равное 2000. Это ограничение, запрашиваемое клиентом, не может переопределить ограничения, установленные в конфигурации сервера. Независимо от ограничения размера, запрошенного клиентом, ограничение размера сервера переопределяет его. Обратитесь к администратору сервера каталогов и попросите увеличить предельный размер.

person Terry Gardner    schedule 03.07.2012
comment
если вы не смогли изменить его в запросе, пользователи и компьютеры Active Directory также не будут работать. Когда я получаю сообщение об ограничении 2000 записей в этом инструменте, я изменяю настройки на более высокое значение, и это работает. так что то, что вы написали, мне кажется не совсем корректным. - person Asaf Magen; 24.06.2021