spring-projects / spring-ldap

Spring LDAP
https://spring.io/spring-ldap
Apache License 2.0
342 stars 481 forks source link

No matching response control found #876

Closed avpdiver closed 2 weeks ago

avpdiver commented 4 months ago

I am using OpenLDAP 2.6.7.

POM file looks like this:

 <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>3.2.5</version>
      <relativePath/>
</parent>
<properties>
        <java.version>17</java.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-ldap</artifactId>
    </dependency>
        ...
</dependencies>
...

My code:

final var sc = new SearchControls();
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
sc.setTimeLimit(10_000);
sc.setCountLimit(size);
sc.setReturningAttributes(new String[]{"uid", "mail", "cn", "givenName"});

PagedResultsDirContextProcessor processor = null;
var cookie = new PagedResultsCookie(UUID.randomUUID().toString().getBytes());
var currentPage = 0;
do {
        processor = new PagedResultsDirContextProcessor(size, cookie);
        final var results = ldapTemplate
                    .search(
                            "ou=users",
                            "(&(objectClass=person)(uid=*))",
                            sc,
                            (AttributesMapper<UserDtoOut>) attrs -> {
                                final var dto = new UserDtoOut();
                                dto.setUid(getAttribute("uid", attrs));
                                dto.setEmail(getAttribute("mail", attrs));
                                dto.setSurname(getAttribute("sn", attrs));
                                dto.setFirstname(getAttribute("givenName", attrs));
                                return dto;
                            },
                            processor
                    );
        if (currentPage == page) {
             return results;
        }
        cookie = processor.getCookie();
        currentPage++;
} while (processor.hasMore());

And pagination doesn't work. I think because of there are entries in log: No matching response control found - looking for 'class javax.naming.ldap.PagedResultsResponseControl.

vboerner commented 1 month ago

I am facing the same problem when I want to talk to an openldap server. If I query an ActiveDirectory page by page, everything works as planned.

I request the first page from openldap and get the data with the responseControls in response. The cookie is read from the responseControls, processed and added as requestControls in the request for the second page and sent to openldap.

From my perspective, everything looks correct up to this point.

The server, however, always responds with the following error message: javax.naming.CommunicationException: [LDAP: error code 2 - paged results cookie is invalid];

This means that the problem always occurs when requesting the second page...

Does anyone have any ideas or tips that could help me to solve the problem and query openldap page by page?

vboerner commented 1 month ago

I did some more research on this topic and I found out that the paging cookie is only valid within the same connection for OpenLDAP. But for Active Directory it can be different connections.

In order for a paged results cookie to work with OpenLDAP, it is necessary that the same underlying connection is used for each paged results call. This can be accomplished using the SingleContextSource.

You can wrap your existing ContextSource in a SingleContextSource. And pass it to the LdapTemplate:

@Bean
public SingleContextSource singleContextSource(ContextSource contextSource) {
  return new SingleContextSource(contextSource.getReadOnlyContext());
}

@Bean
public LdapTemplate ldapTemplate(SingleContextSource singleContextSource) {
  final LdapTemplate ldapTemplate = new LdapTemplate(singleContextSource);
  ldapTemplate.setIgnorePartialResultException(true);
  return ldapTemplate;
}

This solution solves the problem for me.

jzheaux commented 2 weeks ago

Thanks for the pointer, @vboerner. Given your response, I think we are okay to close this issue. @avpdiver, if you continue to have trouble, please post this question to StackOverflow with the spring-ldap tag and then paste the link to that here. We can continue investigating over there.