Tomcat 8 – LDAP:NameNotFoundException错误代码32,剩余名称为空字符串
尝试将应用程序从WebLogic 12.2.1迁移到Tomcat 8.5.4 ,Weblogic下的内容是作为LDAP连接的外部JNDI提供程序的条目已迁移到Tomcat下的新Resource
。
遵循Stack Overflow的这个建议 ,自定义LdapContextFactory
已被打包为Tomcat lib
文件夹下的新jar
文件。
在Tomcat server.xml
文件中,已配置以下GlobalNamingResources/Resource
:
通过嵌入在Eclipse中的Apache Directory Studio / LDAP Browser等LDAP浏览器浏览LDAP目录时,上述连接可正常工作。
自定义com.sample.custom.LdapContextFactory
非常简单:
public class LdapContextFactory implements ObjectFactory { public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { Hashtable env = new Hashtable(); Reference reference = (Reference) obj; Enumeration references = reference.getAll(); while (references.hasMoreElements()) { RefAddr address = references.nextElement(); String type = address.getType(); String content = (String) address.getContent(); env.put(type, content); } return new InitialLdapContext(env, null); } }
但是,在启动时,Tomcat会抛出以下exception:
07-Sep-2016 15:04:01.064 SEVERE [main] org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans Exception processing Global JNDI Resources javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of: '' ]; remaining name '' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3160) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3081) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2888) at com.sun.jndi.ldap.LdapCtx.c_listBindings(LdapCtx.java:1189) at com.sun.jndi.toolkit.ctx.ComponentContext.p_listBindings(ComponentContext.java:592) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.listBindings(PartialCompositeContext.java:330) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.listBindings(PartialCompositeContext.java:317) at javax.naming.InitialContext.listBindings(InitialContext.java:472) at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:136) at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:145) at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:110) at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.lifecycleEvent(GlobalResourcesLifecycleListener.java:82) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401) at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:345) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:784) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152) at org.apache.catalina.startup.Catalina.start(Catalina.java:655) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:355) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:495)
类似的问题和调查表明LDAP DN无效,但是:
- 相同的LDAP配置可通过LDAP客户端正常工作
- 实际上没有执行任何搜索,在启动时Tomcat会抛出此exception而不进行任何查询
- 该错误表明一个空字符串
''
作为remaining name
,因此显然不是真正找不到的东西
问题 :这是将外部JNDI提供程序条目从WebLogic迁移到Tomcat的正确方法吗? 如何修复剩余名称为空的无效LDAP DN条目? 在某处配置它可能是一个缺少的baseDN
吗?
更新
将LdapContextFactory
更改为以下内容时会发生同样的错误,如通过注释所示:
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { Hashtable env = new Hashtable(); Reference reference = (Reference) obj; Enumeration references = reference.getAll(); String providerUrl = "no valid URL"; while (references.hasMoreElements()) { RefAddr address = references.nextElement(); String type = address.getType(); String content = (String) address.getContent(); switch (type) { case Context.PROVIDER_URL: env.put(Context.PROVIDER_URL, content); providerUrl = content; break; default: env.put(type, content); break; } } InitialLdapContext context = null; Object result = null; try { context = new InitialLdapContext(env, null); LOGGER.info("looking up for " + providerUrl); result = context.lookup(providerUrl); } finally { if (context != null) { context.close(); } } LOGGER.info("Created new LDAP Context"); return result; }
通过日志记录确认更改,以确保正确部署。
默认情况下,涉及的侦听器在server.xml
文件的顶部定义为
并且不能根据官方文档禁用:
Global Resources Lifecycle Listener初始化
server.xml
定义的Global JNDI资源,作为Global Resources元素的一部分。 没有这个监听器,全局资源都不可用。
在Tomcat版本8.5.5和7.0.69上也会发生同样的情况:只需添加上面的新全局资源以及提供上述工厂的附加jar,将抛出指向空的剩余名称的exception。
通过使用问题中提供的第一个工厂实现将LDAP模式DN附加到java.naming.provider.url
属性, java.naming.provider.url
消失了。
在此上下文中使用的LDAP客户端的屏幕截图下方,嵌入在Eclipse中的Apache Directory Studio / LDAP浏览器,只需使用问题的初始值就可以从中浏览相关的LDAP。
通过将Root元素的模式DN附加到连接URL,exception消失,现在通过Tomcat 8中的JNDI共享LDAP资源。
作为故障排除结果的进一步细节 :
在Tomcat 8中,全局资源是通过全局资源侦听器处理的, GlobalResourcesLifecycleListener
默认在server.xml
文件中定义。 这样的监听器在bean创建时调用 context.listBindings("")
,从而有效地浏览LDAP目录。
这种初始浏览可能很可能是Tomcat和WebLogic之间的区别,其中LDAP仅在需要时通过JNDI查找,因此通过直接查询,而不是在启动时使用通用查询。 因此,在Tomcat中,LDAP url需要进一步的细节,即,作为其url的一部分稍微不同的配置,以直接指向有效的基本DN。
从官方WebLogic文档 :
启动时,WebLogic Server会尝试连接到JNDI源。 如果连接成功,WebLogic Server将在本地JNDI树中设置请求的对象和链接,使其可供WebLogic Server客户端使用。
因此,连接比listBindings
简单得多:
枚举命名上下文中绑定的名称以及绑定到它们的对象。 不包括任何子上下文的内容。