简体   繁体   中英

How to authenticate a user against AD in Java

I'm using JNDI library to access to an AD from Java Webapp. I authenticate agaisnt the AD via LDAP using a technical user as follows:

    Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
    ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT);
    ldapEnv.put(Context.PROVIDER_URL, providerUrl);
    ldapEnv.put(Context.SECURITY_AUTHENTICATION,
            SECURITY_AUTHENTICATION_SIMPLE);
    ldapEnv.put(Context.SECURITY_PRINCIPAL, principal);
    ldapEnv.put(Context.SECURITY_CREDENTIALS, credentials);
    return new InitialDirContext(ldapEnv);

I use this user to read and write from/to AD.

But after that, I don't know how to authenticate the final user who is really accessing to my webapp with his user and a password.

I read about using find method from Context class but I'm not sure how to do or how to build the the search filter. For example

(&(cn= ....

I don't know either how to find for all users in the AD. I would like to show in my webapp a list of all available users in AD

-To Authenticate a user

Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "LDAP://url/");

env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "domain\\user_name");
env.put(Context.SECURITY_CREDENTIALS, "password");

InitialLdapContext ctx = new InitialLdapContext(env,null);
boolean authenticated = (ctx != null) ? true : false;

-To Get all users' names

public ArrayList<String> getAllUsers(LdapContext ctx) {
    ArrayList<String> users = new ArrayList<>();
    try {
        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String[] attrIDs = {"cn"};
        constraints.setReturningAttributes(attrIDs);

        NamingEnumeration answer = ctx.search("dc=example,dc=com", "(&(cn=*))", constraints);

        while (answer.hasMore()) {
            Attributes attrs = ((SearchResult) answer.next()).getAttributes();
            users.add(attrs.get("cn").toString().replace("cn:", ""));
        }

    } catch (Exception ex) {
    }
    return users;
}

-To Search a particular use

public String getUserName(String username, LdapContext ctx) {
    try {
        SearchControls constraints = new SearchControls();
        constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String[] attrIDs = {"cn"};
        constraints.setReturningAttributes(attrIDs);

        NamingEnumeration answer = ctx.search("OU=Employees,OU=Users,DC=sub_domain,DC=domain,DC=com", "uid=" + username, constraints);

        if (answer.hasMore()) {
            Attributes attrs = ((SearchResult) answer.next()).getAttributes();
            return attrs.get("cn").toString().replace("cn:", "");
        } else {
            return null;
        }

    } catch (Exception ex) {
    }
    return null;
}

You can get more details about search query from this

Why don't you use the same for each user to authenticate.

see http://docs.oracle.com/javase/jndi/tutorial/ldap/security/ldap.html

If you get the context for that user, that means username & password is correct. If not, not you get the exception & send it o user login screen etc.

Don't forget to close the Context in finally block if authenticated.

I believe this link will save your day:
http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory You can authenticate a user and list users of a domain.

-To authenticate you need to create dir context , just like you mentioned in you question, for each user trying to to login.

--Or if you have Weblogic as your Appserver , you can make use of WL container authentication to handle user login by configuring AD as an authenticatoe in WL and protecting your login URL. : Read more Configuring container-managed security in Weblogic

-To list all users under a Root DSE or a certain Base DN

  1. Create a Dir Context to pointing to the Root DSE or a DN under it

    DirContext ctx = InitialDirContext(ldapEnv);

  2. Do context.search() passing returning attributes, search controls and the search filter matching user object classes and login attribute

    SearchControls controls = new SearchControls(); controls.setReturningAttributes(new String[]{"cn" ,"objectGUID"}); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); String filter = "(&(cn=*)(|(objectclass=person) (objectclass=organizationalPerson)))";

    NamingEnumeration searchResult = ctx.search("", filter, controls);

-To search a particular user , modify the filter to match the user cn or any other attribute

String filter = "(&(cn=Rafa Romero)(|(objectclass=person)(objectclass=organizationalPerson)))";

Most servlet containers can be configured to authenticate via LDAP, that would be significantly more secure and reliable than rolling your own authentication code.

For example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM