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

3

7

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 (below) 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.

Interpretative answered 25/7, 2017 at 6:31 Comment(0)
G
6

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[]{"*","+"};
Graben answered 28/7, 2017 at 19:54 Comment(5)
Hi Perre, thanx for responding. I tried your suggested code but it throws null pointer exception and also the class DistinguishedNameis deprecated.Interpretative
Please see UPDATE (02-Aug-2017), above in the question area.Interpretative
@Interpretative : I'm trying to think of other possibilities and one that comes to mind is that maybe you're connecting to a Domain Controller (DC) that does not have all these attributes. Can you confirm that the URL you use to connect to LDAP is the same in your code as the one in your screenshot of your LDAPBrowser? If not, look into that. Otherwise, I'm not sure what's wrong, that attribute should really be there...Graben
@Shiva: yes, DistinguishedName is deprecated but wanted to see if that old way of doing things worked. Where do you get the null pointer exception?Graben
Shiva: yet another suggestion to try: use a contextMapper instead of an attributeMapper and see what you can get (maybe use the debugger to inspect what's returned/available). Ex: new ContextMapper(){ @Override public Object mapFromContext(Object ctx) { DirContextAdapter context = (DirContextAdapter)ctx; adUserBean.setTitle(context.getStringAttributes("title"); } });Graben
C
1

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

Carrico answered 28/7, 2017 at 3:28 Comment(2)
Hi Ryan, thanx for responding. Here, ADUserAttributesMapper is a class that implements org.springframework.ldap.core.AttributesMapper interface. It maps the fetched attributes to the properties of a Java POJO bean. Does this limit the number of attributes returned from the LDAP query search? Is there any other mapper?Interpretative
Can you update your question to include this implementation?Carrico
M
0

Change ldap port from 3268 to 389

Marje answered 13/9, 2022 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.