Java – try to configure LDAP as a JNDI resource in Tomcat
I have an LDAP server that I use to authenticate users in the Tomcat web application I'm using jndirealm, which is configured in the context file, which works well
I also need to search for user information in LDAP I've figured out how to do this using the "JNDI method", and I make it work outside Tomcat by creating my own JNDI context using a hash table However, instead of configuring the JNDI attribute in the code, I want to create a JNDI rsource in the context file next to the real configuration
I think I will do something like this:
<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" />
But Tomcat tells me that the resource cannot be created or when I try to initialize with something like this:
Context initctx = new InitialContext(); DirContext ctx = (DirContext) initctx.lookup("java:comp/env/ldap");
Tomcat told me "cannot create resource instance" I'm still on my web The correct resource ref is added to the XML file, so I don't think that's the problem
Since LDAP is used with the JNDI method, I assume it should be able to be configured as a resource, right? What did I miss?
Solution
This answer is a little late, but it may be useful to other users It is based on ejp's answer
The following solutions were tested on Apache Tomcat 7 If necessary, you can replace ldapcontext with dircontext
Create an objectfactory
Create a class that implements objectfactory to instantiate 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; } }
Define your resources
Add the following to the context XML, reference the factory and define the value to create an 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>
If you need to add more attributes / values to the asset, consider updating the objectfactory created above to read these new attributes / values
Use your resources
Inject your resources wherever you need them:
@Resource(name = "ldap/LdapResource") private LdapContext bean;
Or refer to:
Context initialContext = new InitialContext(); LdapContext ldapContext = (LdapContext) initialContext.lookup("java:comp/env/ldap/LdapResource");
See more
The Apache Tomcat documentation explains how to add custom resource factories