Попытка настроить LDAP как ресурс JNDI в Tomcat

У меня есть сервер ldap, который я использую для аутентификации пользователей в веб-приложении tomcat. Я использую JNDIRealm, и он настроен в файле контекста, и это отлично работает.

Мне также нужно будет искать ldap для информации пользователя. Я выяснил, как это сделать с помощью "метода jndi", и я отлично работаю за пределами tomcat, создав собственный контекст jndi с помощью хэш-таблицы. Однако вместо настройки свойств jndi в коде я хотел бы создать JNDI Rsource в моем контекстном файле прямо рядом с конфигурацией Realm.

Я думаю, что я бы сделал что-то вроде этого:

<Resource 
  name="ldap"
  auth="Container"
  type="com.sun.jndi.ldap.LdapCtxFactory"
  java.naming.factory.initial="com.sun.jndi.ldap.LdapCtxFactory"
  java.naming.provider.url="ldap://localhost:389"
  java.naming.security.authentication="simple"
  java.naming.security.principal="uid=rjcarr,dc=example"
  java.naming.security.credentials="abc123"
/>

Но либо tomcat сообщает мне, что ресурс не может быть создан, или когда я пытаюсь инициализировать его примерно так:

Context initctx = new InitialContext();
DirContext ctx = (DirContext) initctx.lookup("java:comp/env/ldap");

Tomcat сообщает мне: "Невозможно создать экземпляр ресурса". Я также добавил правильный ресурс-ref в моем файле web.xml, поэтому я не думаю, что проблема.

Поскольку LDAP используется с JNDI-методом, я предполагаю, что он должен быть настроен как ресурс, правильно? Что мне не хватает?

Ответ 1

Этот ответ немного запоздал, но, вероятно, он будет полезен другим пользователям. Он основан на ответе EJP.

Следующее решение было протестировано на Apache Tomcat 7.
Если вам нужно, вы можете заменить LdapContext с DirContext.

Создайте ObjectFactory

Создайте класс, который реализует ObjectFactory для создания LdapContext:

public class LdapContextFactory implements ObjectFactory {

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

        Hashtable<Object, Object> env = new Hashtable<Object, Object>();
        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();

            switch (type) {

            case Context.INITIAL_CONTEXT_FACTORY:
                env.put(Context.INITIAL_CONTEXT_FACTORY, content);
                break;

            case Context.PROVIDER_URL:
                env.put(Context.PROVIDER_URL, content);
                break;

            case Context.SECURITY_AUTHENTICATION:
                env.put(Context.SECURITY_AUTHENTICATION, content);
                break;

            case Context.SECURITY_PRINCIPAL:
                env.put(Context.SECURITY_PRINCIPAL, content);
                break;

            case Context.SECURITY_CREDENTIALS:
                env.put(Context.SECURITY_CREDENTIALS, content);
                break;

            default:
                break;
            }
        }

        LdapContext context = new InitialLdapContext(env, null);
        return context;
    }
}

Определите свой ресурс

Добавьте следующее в context.xml, ссылаясь на factory и определяя значения для создания LdapContext instance:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    ...
    <Resource name="ldap/LdapResource" auth="Container"
        type="javax.naming.ldap.LdapContext"
        factory="com.company.LdapContextFactory"
        singleton="false" 
        java.naming.factory.initial="com.sun.jndi.ldap.LdapCtxFactory"
        java.naming.provider.url="ldap://127.0.0.1:389"
        java.naming.security.authentication="simple"
        java.naming.security.principal="username"
        java.naming.security.credentials="password" />
</Context>

Если вам нужно добавить дополнительные атрибуты/значения в свой ресурс, подумайте о том, чтобы обновить созданный выше ObjectFactory, чтобы прочитать эти новые атрибуты/значения.

Используйте свой ресурс

Внесите свой ресурс туда, где вам нужно:

@Resource(name = "ldap/LdapResource")
private LdapContext bean;

Или посмотрите:

Context initialContext = new InitialContext();
LdapContext ldapContext = (LdapContext)
    initialContext.lookup("java:comp/env/ldap/LdapResource");

Подробнее

Документация Apache Tomcat объясняет как добавить специализированные фабрики ресурсов.

Ответ 2

Ты готовишься. Тип ресурса Tomcat должен быть классом, который реализует javax.naming.spi.ObjectFactory. См. Документацию Tomcat для пользовательских ресурсов.