Tomcat 8-LDAP: код ошибки NameNotFoundException 32, оставшаяся пустая строка имени

попытка переноса приложения из WebLogic 12.2.1 to Tomcat 8.5.4, что под Weblogic была запись как иностранные поставщики JNDI для подключения LDAP был перенесен на новый Resource в Tomcat.

после этот совет при переполнении стека пользовательский LdapContextFactory был упакован как новый jar файл под Tomcat .

в Tomcat следующий GlobalNamingResources/Resource был настроен:

    <Resource name="ldapConnection" 
        auth="Container"
        type="javax.naming.ldap.LdapContext"
        factory="com.sample.custom.LdapContextFactory"
        singleton="false"
        java.naming.referral="follow"
        java.naming.factory.initial="com.sun.jndi.ldap.LdapCtxFactory"
        java.naming.provider.url="ldap://some.host:389"
        java.naming.security.authentication="simple"
        java.naming.security.principal="CN=some,OU=some,OU=some,DC=some,DC=a,DC=b"
        java.naming.security.credentials="password"
        com.sun.jndi.ldap.connect.pool="true"
        com.sun.jndi.ldap.connect.pool.maxsize="10"
        com.sun.jndi.ldap.connect.pool.prefsize="4"
        com.sun.jndi.ldap.connect.pool.timeout="30000" />

соединение выше отлично работает при просмотре каталога LDAP через браузер LDAP, такой как Apache Directory Studio / браузер LDAP, встроенный в Eclipse.

таможни com.sample.custom.LdapContextFactory довольно проста:

public class LdapContextFactory implements ObjectFactory {

    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
            throws Exception {

        Hashtable<Object, Object> env = new Hashtable<>();
        Reference reference = (Reference) obj;
        Enumeration<RefAddr> 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 выдает следующее исключение:

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)

как вопросы и исследования предполагают недопустимое DN LDAP, но:

  • та же конфигурация LDAP отлично работает через клиент LDAP
  • поиск фактически не выполняется, во время запуска Tomcat выдает это исключение без какого-либо запроса
  • ошибка предполагает пустую строку '' as remaining name, следовательно не совсем что-то не нашел, видимо

вопрос(ы): это правильный способ переноса иностранные поставщики JNDI запись из WebLogic в Котяра? Как исправить недопустимую запись DN LDAP с пустым оставшимся именем? Может быть, это пропавший baseDN где-то настроить?


обновление
Такая же точная ошибка происходит при изменении LdapContextFactory к следующему, как предложено через комментарии:

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
        throws Exception {

    Hashtable<Object, Object> env = new Hashtable<>();
    Reference reference = (Reference) obj;
    Enumeration<RefAddr> 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;
}

изменение подтверждается путем регистрации, чтобы убедиться, что оно было правильно развернуто.

вовлеченный слушатель определяется по умолчанию в верхней части as

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

и не может быть отключен в соответствии с официальная документация:

прослушиватель жизненного цикла глобальных ресурсов инициализирует Глобальные ресурсы JNDI, определенные в server.xml как часть элемента глобальных ресурсов. Без этого слушателя ни один из глобальных ресурсов не будет доступен.


то же самое происходит и в версии Tomcat 8.5.5 и 7.0.69: просто добавляя новый глобальный ресурс, как указано выше, и дополнительный jar, предоставляющий фабрику выше, исключение, указывающее на пустое оставшееся имя, будет выброшено.

1 ответов


stacktrace ушел, добавив к java.naming.provider.url свойство DN схемы LDAP, используя первую реализацию фабрики, представленную в вопросе.

ниже скриншота клиента LDAP, используемого в этом контексте, браузер Apache Directory Studio / LDAP, встроенный в Eclipse, из которого можно было просмотреть соответствующий LDAP, просто используя начальные значения вопроса.

enter image description here

путем добавления DN схемы корневой элемент URL-адреса соединения, исключение исчезло, и ресурс LDAP теперь совместно используется через JNDI в Tomcat 8.


дополнительные сведения в результате устранения неполадок:

в Tomcat 8 Глобальные ресурсы обрабатываются через глобальный прослушиватель ресурсов,GlobalResourcesLifecycleListener, определенный по умолчанию в . Такой слушатель!--22-->вызывает a context.listBindings("") при создании компонента, следовательно, эффективно просматривая LDAP справочник.

этот начальный просмотр может, скорее всего, быть разницей между Tomcat и WebLogic, где LDAP просматривается через JNDI только при необходимости, следовательно, через прямой запрос, а не при запуске с общим запросом. Таким образом, в Tomcat url LDAP потребуется дополнительная информация, то есть немного другая конфигурация как часть его url, чтобы напрямую указать на допустимое базовое DN.

официальных WebLogic documentation:

при запуске WebLogic Server пытается подключиться к источнику JNDI. Если соединение успешно, WebLogic Server устанавливает запрошенные объекты и ссылки в локальном дереве JNDI, делая их доступными для клиентов WebLogic Server.

следовательно, соединение гораздо проще, чем listBindings:

перечисляет имена, связанные в именованном контексте, вместе с объектами, связанными с ними. Содержание подконтексты не включенный.