Wednesday, August 2, 2017

Why does Spring LDAP's LdapTemplate not return title, department & company attributes?

Leave a Comment

I'm using spring-ldap-core-2.3.1.RELEASE.jar over JDK 1.8 & Tomcat 8.0 to access AD information through LdapTemplate. The attributes such as title,department & company are not being returned by the ldapTemplate.search(..,.,..) method.

I'm using the following lines of code to search :-

LdapQuery ldapQuery = LdapQueryBuilder.query()                                        .where("objectclass").is("user")                                        .and("objectcategory").is("person")                                        .and("cn").like(strWildcardText+"*"); ldapTemplate.search(ldapQuery, new ADUserAttributesMapper()); 

Following is the ADUserAttributesMapper class :-

public class ADUserAttributesMapper implements AttributesMapper<ADUserBean> {     @Override     public ADUserBean mapFromAttributes(Attributes attributes) throws NamingException {         if(attributes==null) {             return null;         }          adUserBean.setName((attributes.get("name")!=null) ? attributes.get("name").get().toString() : null);         adUserBean.setCommonName((attributes.get("cn")!=null) ? attributes.get("cn").get().toString() : null);         adUserBean.setDisplayName((attributes.get("displayname")!=null) ? attributes.get("displayname").get().toString() : null);         adUserBean.setGivenName((attributes.get("givenname")!=null) ? attributes.get("givenname").get().toString() : null); // for FIRST NAME         adUserBean.setMiddleName((attributes.get("initials")!=null) ? attributes.get("initials").get().toString() : null); // for MIDDLE NAME / INITIALS         adUserBean.setLastName((attributes.get("sn")!=null) ? attributes.get("sn").get().toString() : null); // for LAST NAME         adUserBean.setDepartment((attributes.get("department")!=null) ? attributes.get("department").get().toString() : null);         adUserBean.setUserPrincipalName((attributes.get("userprincipalname")!=null) ? attributes.get("userprincipalname").get().toString() : null); // Logon Name         adUserBean.setsAMAccountName((attributes.get("samaccountname")!=null) ? attributes.get("samaccountname").get().toString() : null); // Logon Name (pre-Windows 2000)         adUserBean.setDistinguishedName((attributes.get("distinguishedname")!=null) ? attributes.get("distinguishedname").get().toString() : null);         adUserBean.setMailID((attributes.get("mail")!=null) ? attributes.get("mail").get().toString() : null);         adUserBean.setTitle((attributes.get("title")!=null) ? attributes.get("title").get().toString() : null); // Job Title         adUserBean.setTelephoneNumber((attributes.get("telephonenumber")!=null) ? attributes.get("telephonenumber").get().toString() : null);         adUserBean.setObjectCategory((attributes.get("objectcategory")!=null) ? attributes.get("objectcategory").get().toString() : null);          return adUserBean;     } } 

The title,department & company attributes belong to the Organization tab of the AD user properties as shown in the below image :- enter image description here

Also, from the General tab the initials(initials) attribute is not being picked up/listed by Spring-LDAP's ldapTemplate. The LdapQueryBuilder.query() object has access to attributes(...) method that takes a string array of attribute names that are to be fetched. But even after mentioning them there explicitly, values for attributes such as initials, title, department & company are not returned.

The LDAP Browser plugin within the Eclipse IDE lists the title,department & company properties under the Organization tab without a problem.

Even the com4j API returns the title, department & company attributes.

Is there any configuration that is limiting the attribute(s) listing or is it a limitation with Spring-LDAP API itself? Are these attributes not part of BasicAttributes? How to fetch these attributes through Spring-LDAP?

UPDATE (01-Aug-2017): The plain Java JNDI approach/code does NOT return department,company,title attributes (even with these attributes being explicitly mentioned in attributes string array), but surprisingly it does return the initials attribute value.

UPDATE (02-Aug-2017): Similar to @Pierre's suggestion tried the following code using SearchControls object :-

String strFilter= "(&(objectclass=top)(cn=cgma*))"; String[] attrs = new String[] {"cn","givenName","sn","initials","title","department","company"}; long maxResults = 10; // for example  SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setReturningAttributes(attrs); searchControls.setCountLimit(maxResults); List<String> aLstOfADUsers = ldapTemplate.search("",strFilter,searchControls,new AttributesMapper<String>()                                                                       {                                                                         public String mapFromAttributes(Attributes attrs) throws NamingException {                                                                             try                                                                             {                                                                                 System.out.println(attrs.toString());                                                                                 return attrs.get("cn").get().toString();                                                                             }                                                                             catch(Exception ex) {                                                                                 ex.printStackTrace();                                                                                 return null;                                                                             }                                                                         }                                                                      });  return aLstOfADUsers; 

Even this does not return the initials, title, company & department attribute values.

2 Answers

Answers 1

The person attributes might be internal attributes which you wouldn't get back by default. You can specify explicitly which attributes you want returned BUT not in the search method you're using (the one where you pass in an LdapQuery object). If you take a look at the org.springframework.ldap.core.LdapTemplate class, it doesn't seem like you can pass in the SearchControls object to the method signature you're using. So, to be able to specify attributes to fetch, replace this:

LdapQuery ldapQuery = LdapQueryBuilder.query()                                        .where("objectclass").is("user")                                        .and("objectcategory").is("person")                                        .and("cn").like(strWildcardText+"*"); ldapTemplate.search(ldapQuery, new ADUserAttributesMapper()); 

With this:

        LikeFilter filter = new LikeFilter("cn", strWildcardText+"*");          // list of attributes to retrieve         String[] attrs = new String[] {"title","department","company"};         long maxResults = 10; // for example           SearchControls searchControls = new SearchControls();         searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);         searchControls.setReturningAttributes(attrs);         searchControls.setCountLimit(numResults);          ldapTemplate.search(DistinguishedName.EMPTY_PATH, filter.encode(), searchControls, new ADUserAttributesMapper()); 

The above should work. You could also try something like this (I haven't tried that yet):

ldapTemplate.search( "dc=yourorg,dc=com",          "(&(cn=" +strWildcardText + "*)(&(objectClass=person)(objectcategory=person)))",         SearchControls.SUBTREE_SCOPE,         new String[]{ "title","department","company" },         new ADUserAttributesMapper() ); 

Finally, to get ALL attributes back, ask to retrieve ALL attributes in the code above (my above example only asked for 3 attributes, this would return ALL of them):

        String[] attrs = new String[]{"*","+"}; 

Answers 2

This is based on your AttributesMapper. I don't know what ADUserAttributesMapper is, so you'd have to provide that implementation.

Here's the javadoc for this interface. http://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/core/AttributesMapper.html

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment