简体   繁体   中英

LDAP “simple” User authentication (JNDI - Tomcat) not stable?

I'm new to java LDAP authentication using JNDI. When shearching over internet for tutorials, I found a sample code from fallowing URL,

http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory

I'm creating web app using JavaServlet & JSP.

Just I want is Authenticate users using LDAP.

My server is Apache,Tomcat and I'm using Xampp for that.

Now the system is authenticating users well using LDAP but some times it will throwing fallowing exception.

"javax.naming.NamingException: Failed to connect to xxxxxx.com"

It will remain about an hour, automatically system will again working well.

can any one tell me what would be the issue?

I have changed the server to GlassFish, but issue is same.

Here my code,

 public static LdapContext getConnection (String username, String password,
            String domainName, String serverName) throws NamingException {

        if (domainName == null) {
            try {
                String fqdn = java.net.InetAddress.getLocalHost()
                        .getCanonicalHostName();
                if (fqdn.split("\\.").length > 1) {
                    domainName = fqdn.substring(fqdn.indexOf(".") + 1);
                }
            } catch (java.net.UnknownHostException e) {
            }
        }

        if (password != null) {
            password = password.trim();
            if (password.length() == 0) {
                password = null;
            }
        }

        Hashtable props = new Hashtable();

        String principalName = username + "@" + domainName;

        props.put(Context.SECURITY_PRINCIPAL, principalName);

        if (password != null) {
            props.put(Context.SECURITY_CREDENTIALS, password);
        }        

        String ldapURL = "ldap://"
                + ((serverName == null) ? domainName : serverName + "."
                        + domainName) +":389/";             

        String Auth_Metho="simple";      

        props.put(Context.SECURITY_AUTHENTICATION,
                Auth_Metho); 
        props.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        props.put(Context.PROVIDER_URL, ldapURL);
        props.put("com.sun.jndi.ldap.read.timeout", "0");
        try {           
            return new InitialLdapContext(props, null);
        } catch (javax.naming.CommunicationException e) {
            throw new NamingException("Failed to connect to " + domainName
                    + ((serverName == null) ? "" : " through " + serverName));
        } catch (NamingException e) {
            throw new NamingException("Failed to authenticate " + username
                    + "@" + domainName
                    + ((serverName == null) ? "" : " through " + serverName));
        }
    }

//Then call it as....

String SreverName = "xxxxxx.com";
String userName = "xxxxx";
String password ="xxxxx";

 LdapContext ctx;
        try {
            ctx = ActiveDirectory.getConnection( userName ,
                    password , SreverName);
             ctx.close(); // unameStr, passStr,
             System.out.println("Authenticated!");
        } catch (NamingException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
        }

First, the code you're using is suppressing the real exception. What is the CommunicationException that is occuring? Given this code, there's no way to know.

} catch (javax.naming.CommunicationException e) {
    throw new NamingException("Failed to connect to " + domainName + ((serverName == null) ? "" : " through " + serverName));

Step 1 is to fix this so that you at least have more information as to what the real problem is.

Even without this extra information though, the most likely issue is that the LDAP is being brought down so that a backup or reorg can be run. Most companies run multiple LDAPs and bring them down one at a time so that nightly or weekly maintenance can be performed on them. One way to deal with this is to specify multiple LDAP URLs for the PROVIDER_URL , the LDAP provider will try each URL until a connection is successfully created.

props.put(Context.PROVIDER_URL, "ldap://ldap1.domain.com:389 " +
    "ldap://ldap2.domain.com:389 " +
    "ldap://ldap3.domain.com:389");

You'll probably need to contact your LDAP administrator to obtain the URLs for each individual LDAP. And while you're at it, ask your admin when they take the LDAPs down for maintenance and correlate that against the connection errors you're seeing.

Alternatively, if your company doesn't have a DNS entry for each separate LDAP and the hostname you're using right now has multiple IP addresses associated with it, you could use InetAddress to get all of the IPs and build the PROVIDER_URL from them.

InetAddress[] addresses = InetAddress.getAllByName(ldapHostname);
String providerUrl = "ldap://" + addresses[0].getHostAddress() + ":389";
for(int i = 1; i < addresses.length; i++){
    providerUrl += " ldap://" + addresses[i].getHostAddress() + ":389";
}
props.put(Context.PROVIDER_URL, providerUrl);

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