Raghuram
Raghuram

Reputation: 371

ClassCastException while searching for LDAP user

After migrating to Spring security 4.2.2 (from 3.1), I am hitting the following error in LDAP user search:

java.lang.ClassCastException: com.sun.jndi.ldap.LdapCtx cannot be cast to org.springframework.ldap.core.DirContextAdapter
  at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntryInternal(SpringSecurityLdapTemplate.java:345)
  at org.springframework.security.ldap.SpringSecurityLdapTemplate$3.executeWithContext(SpringSecurityLdapTemplate.java:318)
  at org.springframework.ldap.core.LdapTemplate.executeWithContext(LdapTemplate.java:817)
  at org.springframework.ldap.core.LdapTemplate.executeReadOnly(LdapTemplate.java:803)
  at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleEntry(SpringSecurityLdapTemplate.java:316)
  at org.springframework.security.ldap.search.FilterBasedLdapUserSearch.searchForUser(FilterBasedLdapUserSearch.java:127)
  ...
  ...

I would appreciate any help in resolving the issue. I am using OpenLDAP server for the test if it makes any difference.

Thanks, Raghu

Upvotes: 1

Views: 1796

Answers (1)

Qword
Qword

Reputation: 90

Old question, but I had the same issue and manage to solve it somehow, so I thought I should share.

I'm using Spring Security 4.2.3 and I had something similar:

public AdvisorResponse getAdvisorInfo(final String uid) {
    return cdsLdapTemplate.searchForObject(
            createCriteria(uid), this::mapAdvisorResponse
    );
}

private AdvisorResponse mapAdvisorResponse(final Object ctx) {
    final DirContextAdapter context = (DirContextAdapter) ctx;
    final AdvisorResponse advisor = new AdvisorResponse();
    advisor.setUid(context.getStringAttribute("uid"));
    return advisor;
}

private ContainerCriteria createCriteria(final String uid) {
    return query()
            .base("ou=people")
            .countLimit(1)
            .searchScope(SUBTREE)
            .timeLimit(TIMEOUT)
            .where("uid").is(uid);
}

It used to work flawlessly until I had to run it in an @Async thread, then I started to have the same class cast exception. As suggested here the error seems to be due to a different classloader used in the thread. My solution was to force the correct classloader into the execution thread:

public AdvisorResponse getAdvisorInfo(final String uid) {
    Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

    return cdsLdapTemplate.searchForObject(
            createCriteria(uid), this::mapAdvisorResponse
    );
}

Upvotes: 4

Related Questions