2.1 - Connection and disconnection

LDAP is a protocol that requires users to be connected, and likely identified (authenticated), before sending requests to the server. This connection can potentially be maintained forever. What makes LDAP protocol different from, say, HTTP protocol is that connections are issued explicitly. Here we’ll see how it’s done.

Opening a connection

We can open a secure or a standard connection.

Standard connection

We can first establish a standard connection, where the data is sent and received in clear text (encoded in ASN.1 BER, but not encrypted). This example shows how it’s done:

    LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );

Here we created an unsafe connection locally using the 389 port, with a local server. It’s quite simple to do but not safe because data are not encrypted.

Secure connection

There are two ways to secure a LDAP connection:

  • Either by using LDAPS, which requires a dedicated port (by default, 636)
  • Or by sending a StartTLS extended request which will tell the server to secure the existing connection, keeping the defined LDAP port (by default, 389)

Although LDAPS (LDAP over SSL) is considered as deprecated, many people still use it. The big advantage of not using LDAPS is that you don’t need two different listening ports (one for LDAP -389- and another one for LDAPS -636- ). On the other hand, it’s guarantee to have the communication secured, while you must NOT forget to send the StartTLS operation if you want to secure the communication if you have opened the connection using LDAP.

We will focus on using LDAPS in this guide.

Securing using LDAPS

The only difference with the previous example is that we tell the connection to use SSL, by passing true as a third parameter (incidentally, passing false sets an unsafe connection, which is the default).

Do not forget to stipulate the proper port, too!

Here is an example

    LdapConnection connection = new LdapNetworkConnection( "localhost", 636, true );

Maintaining the connection opened

We keep the connection opened for a limited period of time, defaulting to 30 seconds. This might be not long enough, so one can change this delay by calling the setTimeOut() method :

    LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );
    connection.setTimeOut( 0 );
    ...
    connection.close();

Note: Setting a value equal or below 0 will keep the connection open forever (assuming the connection is not explicitly closed by the client).

Closing the connection

Once the connection is no longer needed (remember that holding a connection keeps the session opened on the server and a socket is held open between the client and the server), then you must close it. This is done by calling the close() method :

    LdapConnection connection = new LdapNetworkConnection( "localhost", 389 );
    ...
    connection.close();

Using a pool of connections

Creating a connection is expensive. If the connection will be reused, or if your application needs multiple connections, you may want to consider using a connection pool.

This process is slightly more complex given that there are many parameters that can be used to tune the pool. Here is an example:

    LdapConnectionConfig config = new LdapConnectionConfig();
    config.setLdapHost( hostname );
    config.setLdapPort( port );
    config.setName( adminDn );
    config.setCredentials( adminPassword );

    DefaultLdapConnectionFactory factory = new DefaultLdapConnectionFactory( config );
    factory.setTimeOut( connectionTimeout );

    // optional, values below are defaults
    GenericObjectPool.Config poolConfig = new GenericObjectPool.Config();
    poolConfig.lifo = true;
    poolConfig.maxActive = 8;
    poolConfig.maxIdle = 8;
    poolConfig.maxWait = -1L;
    poolConfig.minEvictableIdleTimeMillis = 1000L * 60L * 30L;
    poolConfig.minIdle = 0;
    poolConfig.numTestsPerEvictionRun = 3;
    poolConfig.softMinEvictableIdleTimeMillis = -1L;
    poolConfig.testOnBorrow = false;
    poolConfig.testOnReturn = false;
    poolConfig.testWhileIdle = false;
    poolConfig.timeBetweenEvictionRunsMillis = -1L;
    poolConfig.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;

    LdapConnectionPool pool = new LdapConnectionPool(
        new DefaultPoolableLdapConnectionFactory( factory ), poolConfig ) );

This creates a pool of connections that are pre-authenticated. If you don’t use the setName and setCredentials methods, then the pool will contain unauthenticated connections.

The DefaultPoolableLdapConnectionFactory is sufficient for most of the cases.

However some operations result in modifications to the connection itself. For example, when the pool is created, a bind operation will occur with the credentials supplied as part of the configuration.

If you borrow a connection and perform a bind yourself, that would result in the connection being re-bound as a different user.

The next time that connection gets borrowed, things are likely to break.

If you perform any operation that results in a modification of the connection, you should instead use ValidatingPoolableLdapConnectionFactory:

    ...
    LdapConnectionPool pool = new LdapConnectionPool(
        new ValidatingPoolableLdapConnectionFactory( factory ), poolConfig ) );
    ...

A connection pool using this factory will unbind and rebind any connection that was modified while it was borrowed (see the javadoc for more detail). This will be slower due to the additional operations, but not significantly.