Retrieving user attributes from Active Directory u

2019-09-08 07:39发布

问题:

EDIT: I've posted the solution below.

I know you don't like these type of questions, but i've been struggling with this issue for half a day now.

I've written a C# code that fetches user attributes from our Active Directory using LDAP, the code works well.

The code is as follows:

        DirectoryEntry dirEnt = new DirectoryEntry("LDAP://dc=dom,dc=int");
        DirectorySearcher adSearch = new DirectorySearcher(dirEnt);
        adSearch.SearchScope = SearchScope.Subtree;
        adSearch.PageSize = 10000;
        adSearch.Filter = "(&(objectClass=user))";
        SearchResultCollection sColl = adSearch.FindAll();

        foreach (SearchResult sResult in sColl)
        {
            string sConn = sResult.Properties["distinguishedName"][0].ToString();
            DirectoryEntry dirEnt2 = new DirectoryEntry("LDAP://" + sConn);
            ... 
            // dirEnt2 contains ALL attributes for the user
        }

I'm trying to port this code to Java, but it seems like that the technique I used in C# does not work too well in Java.

Using the following code

DirContext context;
ArrayList<String> nList = new ArrayList<String>();
Hashtable env = new Hashtable();
String username = ...;
String password = ...;

try {
    env.put(Context.SECURITY_PRINCIPAL, username);
    env.put(Context.SECURITY_CREDENTIALS, password);

    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, ldapUri);

    try {
       context   = new InitialDirContext(env);
     } catch (NamingException e) {
        throw new RuntimeException(e);
     }

    SearchControls ctrl = new SearchControls();
    ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);

    NamingEnumeration enumeration = context.search("", "(objectClass=user)",
                                                   ctrl);
    while (enumeration.hasMore()) {
        SearchResult result = (SearchResult) enumeration.next();
        Attributes attribs = result.getAttributes();
        NamingEnumeration values = ((BasicAttribute) 
                                     attribs.get("distinguishedName")).getAll();
        while (values.hasMore()) {
            nList.add(values.next().toString());
            }
        }

    } catch (NamingException e) {
        e.printStackTrace();
    }

    for (String sVar : nList ){
        Hashtable env2 = new Hashtable();
        env2.put(Context.SECURITY_PRINCIPAL, username);
        env2.put(Context.SECURITY_CREDENTIALS, password);
        env2.put(Context.INITIAL_CONTEXT_FACTORY, 
                 "com.sun.jndi.ldap.LdapCtxFactory");
        env2.put(Context.PROVIDER_URL, "ldap://DOM/" + sVar);
        Attributes attrs = null;
        try {
            context   = new InitialDirContext(env2);
            attrs = context.getAttributes(sVar);
        } catch (NamingException e) {
            System.out.println(e.toString());
            continue;
        }

        System.out.println(attrs.toString());
    }

Yields that attrs only contains BASIC attributes regarding the user (such as samaccountname, displayname, etc) and no 'email', 'telephone' or any other similar attributes.

Any help on the issue is blessed!

回答1:

Here's the solution, sorry for the messy code/formatting

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.*;

public class UserFetch {
    public static void main(String[] args) {
        try{
            // Activate paged results
            byte[] cookie = null;
            int count=0;
            int total;

            Hashtable env = new Hashtable();

            env.put(Context.INITIAL_CONTEXT_FACTORY, 
            "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.REFERRAL, "follow");
            env.put(Context.SECURITY_AUTHENTICATION, "Simple");
            env.put(Context.SECURITY_PRINCIPAL, "USERNAME@DOM.COM");
            env.put(Context.SECURITY_CREDENTIALS, "PASSWORD");
            env.put(Context.PROVIDER_URL, "ldap://DOM.COM:389");
            LdapContext ctx = new InitialLdapContext(env, null);

            ctx.setRequestControls(new Control[]{ 
                new PagedResultsControl(10000, Control.CRITICAL) });

            do {
                // Perform the search
                NamingEnumeration results =
                ctx.search("dc=DOM,dc=COM", "(&(objectclass=user)(employeeNumber=*))", getSimpleSearchControls());

                // Iterate over a batch of search results
                while (results != null && results.hasMore()) {
                    // Display an entry
                    SearchResult entry = (SearchResult)results.next();
                    Attributes attrs = entry.getAttributes ();
                    System.out.println(attrs.get("SAMAccountName")); // Username
                    System.out.println("Firstname: " + 
                    attrs.get("givenname")); // firstname
                    System.out.println("Lastname: " + attrs.get("sn")); // lastname
                    System.out.println("EmployeeID " + attrs.get("employeeID"));
                    System.out.println("EmployeeNumber: " + 
                    attrs.get("employeeNumber"));
                    // Handle the entry's response controls (if any)
                }
                // 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();
                            cookie = prrc.getCookie();
                        } else {
                            // Handle other response controls (if any)
                        }
                    }
                }

                // Re-activate paged results
                ctx.setRequestControls(new Control[]{
                    new PagedResultsControl(10000, cookie, Control.CRITICAL) });
            } while (cookie != null);
        }  catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static SearchControls getSimpleSearchControls() {
        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        searchControls.setTimeLimit(30000);
        String[] attrIDs =
        { "SAMAccountName", "sn", "givenname", "employeeID", 
            "employeeNumber" };

        searchControls.setReturningAttributes(attrIDs);
        return searchControls;
    }


}


回答2:

Try setting the returned attributes on your SearchControls

ctrl.setReturningAttributes(new String[] {"email", "telephone"});