我们正在使用以下 LDAP JNDI 连接池设置:
DirContext ctx = null;
try
{
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldaps://" + server + ":" + serverPort);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, pUserName);
env.put(Context.SECURITY_CREDENTIALS, pPassword);
env.put(LdapContext.CONTROL_FACTORIES, "com.sun.jndi.ldap.ControlFactory");
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put("com.sun.jndi.ldap.read.timeout", "300000");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
// load the location of keystore that holds trusted root certificates from web.xml
ServletContext context = ApplicationServlet.getApplication().getServlet().getServletContext();
String certificatePath = context.getInitParameter("AD_CERTIFICATE_PATH");
System.setProperty("javax.net.ssl.trustStore", certificatePath);
// System.setProperty("javax.net.debug", "all");
// For connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");
System.setProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain ssl");
System.setProperty("com.sun.jndi.ldap.connect.pool.maxsize", poolMaxSize);
System.setProperty("com.sun.jndi.ldap.connect.pool.prefsize", poolPrefSize);
System.setProperty("com.sun.jndi.ldap.connect.pool.timeout", poolTimeOut);
System.setProperty("com.sun.jndi.ldap.connect.pool.debug", "fine");
ctx = new InitialDirContext(env);
return (DirContext) ctx;
在 Active Directory 中执行搜索后,我们将使用
ctx.close()
显式关闭上下文以将连接释放回池。
通过上述实现,我们面临着连接在获得连接后立即关闭的问题:
12:06:14,837 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-22) Create and use com.sun.jndi.ldap.LdapClient@26a2a0eb[eun1p3-be.stp-prod.st.com:636] 12:06:16,855 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-22) Close com.sun.jndi.ldap.LdapClient@26a2a0eb 12:06:18,301 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-23) Create and use com.sun.jndi.ldap.LdapClient@76e26d4a[eun1p3-be.stp-prod.st.com:636] 12:06:20,353 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-23) Close com.sun.jndi.ldap.LdapClient@76e26d4a 12:06:21,713 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-19) Create and use com.sun.jndi.ldap.LdapClient@4bb50913[eun1p3-be.stp-prod.st.com:636] 12:06:23,746 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-19) Close com.sun.jndi.ldap.LdapClient@4bb50913 12:06:25,366 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-6) Create and use com.sun.jndi.ldap.LdapClient@2a2eecb7[eun1p3-be.stp-prod.st.com:636] 12:06:27,473 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-6) Close com.sun.jndi.ldap.LdapClient@2a2eecb7 12:06:28,757 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-25) Create and use com.sun.jndi.ldap.LdapClient@3c34b0d[eun1p3-be.stp-prod.st.com:636] 12:06:30,855 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-25) Close com.sun.jndi.ldap.LdapClient@3c34b0d 12:06:32,214 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-22) Create and use com.sun.jndi.ldap.LdapClient@6d9ca028[eun1p3-be.stp-prod.st.com:636] 12:06:34,294 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-22) Close com.sun.jndi.ldap.LdapClient@6d9ca028 12:06:35,730 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-23) Create and use com.sun.jndi.ldap.LdapClient@72ed6bb2[eun1p3-be.stp-prod.st.com:636] 12:06:37,753 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-23) Close com.sun.jndi.ldap.LdapClient@72ed6bb2 12:06:39,184 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-19) Create and use com.sun.jndi.ldap.LdapClient@e87ce30[eun1p3-be.stp-prod.st.com:636] 12:06:41,266 ERROR [stderr] (http-eul151.sgp.st.com-10.75.32.13-10080-19) Close com.sun.jndi.ldap.LdapClient@e87ce30
是的,您不仅要关闭所有
Contexts
,还要关闭所有NamingEnumerations
。这就是连接返回池的方式。
您的日志中没有证据表明连接正在关闭。关闭的是
com.sun.jndi.ldap.LdapClients.
我还在我的一个应用程序中使用 LDAP 实现,JDK 是 17。
当我尝试通过带参数的命令独立运行此类文件时,它会成功运行
命令:
java LdapIntegration 178258
但是当我将其放入我们的应用程序服务器(JBoss EAP 7.4)时,它开始给我错误:
Exception Message: javax.naming.NamingException: WFLYNAM0027: Failed instantiate InitialContextFactory com.sun.jndi.ldap.LdapCtxFactory from classloader ModuleClassLoader for Module "deployment.ABC.war" from Service Module Loader [Root exception is java.lang.IllegalAccessException: class org.jboss.as.naming.InitialContext cannot access class com.sun.jndi.ldap.LdapCtxFactory (in module java.naming) because module java.naming does not export com.sun.jndi.ldap to unnamed module @4b488eb5]
经过多次努力,我将以下行放入standalone.conf文件中
JAVA_OPTS="$JAVA_OPTS --add-opens=java.naming/com.sun.jndi.ldap=ALL-UNNAMED"
执行上述命令后,问题消失,但我的 jboss 宕机了。
下面是代码片段
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
env.put("java.naming.provider.url", "ldap://IP:PORT");
env.put("com.sun.jndi.ldap.connect.timeout", "60000");
env.put("java.naming.security.authentication", "simple");
env.put("java.naming.security.principal", "dummy\\"+userid.trim());
try {
ctx = new InitialDirContext(env);
}catch(Exception e1) {
System.out.println("Naming Exception" + e1);
}
SearchControls searchcontrols = new SearchControls();
searchcontrols.setSearchScope(2);
String s1 = "DC=" + "DUMMY2" + ",DC=com";
String s2 = "(&(sAMAccountName=" + userid + ")( distinguishedName=*))";
NamingEnumeration results = null;
Map<String, String> finalRecord = new Hashtable<>();
try {
results = ctx.search(s1, s2, searchcontrols);
System.out.println("results in String " + results.toString());
System.out.println("results " + results);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
System.out.println("attributes "+attributes.toString());
}
} catch (NamingException e) {
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
}
}
}