8

我有一个 ldap 服务器,用于在 tomcat Web 应用程序中对用户进行身份验证。我正在使用 JNDIRealm,它是在上下文文件中配置的,效果很好。

我还需要在 ldap 中搜索用户信息。我已经想出了如何使用“jndi 方法”来做到这一点,并且通过使用哈希表创建我自己的 jndi 上下文,我让它在 tomcat 之外正常工作。但是,我不想在代码中配置 jndi 属性,而是想在 Realm 配置旁边的上下文文件中创建一个 JNDI Rsource。

我想我会做这样的事情:

<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 告诉我“无法创建资源实例”。我还在 web.xml 文件中添加了正确的资源引用,所以我认为这不是问题所在。

由于 LDAP 与 JNDI 方法一起使用,我假设它应该能够配置为资源,对吗?我错过了什么?

4

2 回答 2

4

这个答案有点晚了,但可能对其他用户有用。它基于EJP 的回答

以下解决方案在Apache Tomcat 7上进行了测试。
如果需要,可以替换LdapContextDirContext.

创建对象工厂

创建一个实现ObjectFactory实例化 a的类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中,引用工厂并定义值以创建LdapContext实例:

<?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 的文档解释了如何添加自定义资源工厂

于 2014-11-25T12:52:15.663 回答
2

你在弥补。Tomcat 资源的类型必须是实现 javax.naming.spi.ObjectFactory 的类。有关自定义资源,请参阅 Tomcat 文档。

于 2012-10-28T21:44:55.073 回答