What's the simplest (i.e least complex) possible LDAP operation
I have implemented a pool for LDAP connections using Apache commons-pool. I cannot use the pooling feature provided by JNDI (http://download.oracle.com/javase/jndi/tutorial/ldap/connect/pool.html) because I use SSL connection (with a custom (Oracle-provided) socket factory (java.naming.ldap.factory.socket
env value set) which disqualifies the context from JNDI pooling) to an LDAP server and thus pooling facility inside JNDI is disabled automatically, even if the according pooling property is set.
Now it comes to the point where a pooled instance of InitialDirContext
is returned to the pool and needs to be checked for whether it is still usable and has not been closed by the user or has lost the connection to the LDAP server due to other causes.
This is where I currently look up the DN of a specific user known to exist:
final InitialDirContext ctx = internalPooledLDAPConnection.getCtx();
final Subscriber sub = internalPooledLDAPConnection.getSub();
SearchControls ctls = new SearchControls();
ctls.setSearchScope(2);
ctls.setReturningAttributes(new String[] { "dn"});
NamingEnumeration resultSet = ctx.search(sub.getUserSearchBase()[0], "(&(objectclass=*)(uid=orcladmin))", ctls);
In case this operation does not throw any exception, then the InitialDirContext
inside my internal pooled Ldap connection is still usable and may be safely given out of the pool for re-usage.
However I wonder whether this is the 'cheapest' connection sanity check that can be performed here or whether there exists a much cheaper LDAP operation whi开发者_高级运维ch I could use instead.
An LDAP compare operation would probably be more efficient than a search because there's only a single response (with a search that matches an entry, you're going to have two responses -- one for the entry and a second to indicate the end of the search results).
However, you might also want to consider alternatives to JNDI, as provides a notoriously bad API for LDAP. There are other Java libraries for performing LDAP communication that are vastly better than JNDI. In particular, the UnboundID LDAP SDK for Java (for which I am a developer) provides a feature-rich, easy-to-use, high-performance API for LDAP communication. It has rich connection pooling capabilities, including health checking, failover, and load balancing. See https://docs.ldap.com/ldap-sdk/docs/advantages/comparison.html for a comparison of the capabilities offered by the UnboundID LDAP SDK with JNDI and the Netscape Directory SDK for Java.
LDAP bind is about as simple as you can get. This is the reconnect() method in JNDI.
However there must be reservations about what you are doing. If pooling is disabled via SSL there must be security reasons for it, so you need to do your own security analysis when designing your own pooling.
I had a similar problem (I rolled my own pool). My approach was to expect any pooled connection to be dead. I let my pool do any query twice: 1st time it might fail, so reconnect and try again, but failures from the 2nd attempt are real, and propagate up.
To summarize, instead of using a specific ping query, I let the application's own queries act as potential pings.
As far as cheapest query, this is probably pretty cheap! You might not even need to bind for this one - I can't remember.
// The rootDSE attributes, Microsoft Active Directory
Attributes attrs = ldapContext.getAttributes("");
String ldapRootDN = (String) attrs.get("rootDomainNamingContext").get(0);
We use a check for the control 0.0.0.0.0 which of course never could exist to test if the connection is active. As I recall this is how the OpenLDAP (jldap) call does the check. As the rootDSE for controls it typically, allowed for anonymous, this will check if the connection is good, but not to check the bind status.
Why not send an invalid search for an unknown or garbage attribute. The entire point is simply to ping and not the actual process.
精彩评论