LDAP“简单”用户身份验证(JNDI - Tomcat)不稳定?

时间:2014-08-05 10:41:42

标签: java tomcat java-ee ldap jndi

我是使用JNDI进行Java LDAP身份验证的新手。当通过互联网搜索教程时,我发现了一个来自fallowing URL的示例代码,

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

我正在使用JavaServlet和&amp ;;创建Web应用程序。 JSP。

我想要的是使用LDAP验证用户。

我的服务器是Apache,Tomcat,我正在使用Xampp。

现在,系统正在使用LDAP对用户进行身份验证,但有时会抛出异常情况。

" javax.naming.NamingException:无法连接到xxxxxx.com"

它会保持大约一个小时,系统会自动恢复正常。

任何人都能告诉我这是什么问题吗?

我已将服务器更改为GlassFish,但问题是相同的。

这是我的代码,

 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();
        }

1 个答案:

答案 0 :(得分:0)

首先,您使用的代码是抑制真正的异常。发生的CommunicationException是什么?鉴于此代码,没有办法知道。

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

第1步是解决这个问题,这样你至少可以获得有关真正问题的更多信息。

即使没有这些额外的信息,最可能的问题是LDAP被降低,以便可以运行备份或重组。大多数公司运行多个LDAP并一次关闭一个,以便可以对它们进行夜间或每周维护。解决此问题的一种方法是为PROVIDER_URL指定多个LDAP URL,LDAP提供程序将尝试每个URL,直到成功创建连接。

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

您可能需要与LDAP管理员联系以获取每个LDAP的URL。当您处于此状态时,请询问您的管理员何时将LDAP关闭以进行维护,并将其与您看到的连接错误相关联。

或者,如果您的公司没有针对每个单独的LDAP的DNS条目,并且您现在使用的主机名具有多个与之关联的IP地址,则可以使用InetAddress来获取所有IP并从中构建PROVIDER_URL

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);