Writing a Simple LDAP ProxyLDAPProxyThe OpenDJ LDAP SDK example Proxy demonstrates a simple LDAP proxy that forwards requests
to one or more remote directory servers. Although the implementation is
intended as an example, it does demonstrate use of the asynchronous API,
load balancing, and connection pooling.ConnectionsAsynchronousThe Proxy example sets up connections pools with load balancing to the
directory servers. It passes the connection factories to a
ProxyBackend that handles the requests passed back
to the directory servers. It also sets up an LDAP listener to receive incoming
connections from clients of the Proxy.The ProxyBackend uses separate connection factories,
one for bind operations, the other for other operations. It uses the proxied
authorization control to ensure operations are performed using the bind
identity for the operation.The ProxyBackend's function is to handle each client
request, encapsulating the result handlers that allow it to deal with each
basic operation. It authenticates to the directory server to check incoming
credentials, and adds the proxied authorization control to requests other than
binds. The ProxyBackend handles all operations using
asynchronous connections and methods.Connection PoolingConnectionsPoolingAs shown in the Proxy example, the
Connections.newFixedConnectionPool() returns a connection
pool of the maximum size you specify.[jcp:org.forgerock.opendj.examples.Proxy:--- JCite pools ---]Connections are returned to the pool when you close()
them. Notice that Connections also provides methods to
return ConnectionFactorys with a heart beat check on
connections provided by the factory, and connection factories that
authenticate connections before returning them.Connections in the pool are intended for reuse. The Proxy gets an
authenticated connection, which is a connection where the OpenDJ LDAP
SDK passes a bind request immediately when getting the connection. The Proxy
then uses proxied authorization to handle the identity from the client
requesting the operation. As a rule, either handle binds separately and use
proxied authorization as in the Proxy example, or else make sure that the
first operation on a connection retrieved from the pool is a bind that
correctly authenticates the user currently served by the connection.When you close() a connection from the pool, the
OpenDJ LDAP SDK does not perform an unbind(). This is why
you must be careful about how you manage authentication on connections from a
pool.Load Balancing & FailoverConnectionsLoad balancingThe Connections.newLoadBalancer() method returns a
load balancer based on the algorithm you choose. Algorithms include both
round robin for equitably sharing load across local directory servers, and
also failover usually used for switching automatically from an unresponsive
server group to an alternative server group. The algorithms take collections
of connection factories, such as those that you set up for connection
pooling.The following excerpt shows how to set up round robin load balancing
across directory servers.[jcp:org.forgerock.opendj.examples.Proxy:--- JCite load balancer ---]With multiple pools of directory servers, for example in a deployment
across multiple data centers, also use fail over load balancing. Fail over
load balancing directs all requests to the first (preferred) pool of servers
until problems are encountered with the connections to that pool. Then it
fails over to the next pool in the list. Therefore in each data center you
can set up round robin load balancing, and then set up fail over load
balancing across data centers.// localFactory: ConnectionFactory to servers in the local data center
// remoteFactory: ConnectionFactory for servers in a remote data center
// localFactory and remoteFactory use round robin load balancing "internally".
final List<ConnectionFactory> factories =
Arrays.asList(localFactory, remoteFactory);
final FailoverLoadBalancingAlgorithm algorithm =
new FailoverLoadBalancingAlgorithm(factories);
final ConnectionFactory factory = Connections.newLoadBalancer(algorithm);The algorithms also include constructors that let you adjust timeouts
and so forth.Listening For & Handling Client ConnectionsConnectionsListening forYou create an LDAPListener to handle incoming client
connections. The LDAPListener takes a connection handler
that deals with the connections, in this case connections back to the
directory servers handling client requests.[jcp:org.forgerock.opendj.examples.Proxy:--- JCite listener ---]
The connection handler is a ServerConnectionFactory
to handle requests coming from clients.
The factory takes a request handler implementation
that deals with all supported incoming client requests.
The Proxy example uses a ProxyBackend to handle requests.
The ProxyBackend sends the requests on
to the backend directory servers
and routes the results returned back to client applications.
[jcp:org.forgerock.opendj.examples.Proxy:--- JCite backend ---]
For details about the ProxyBackend implementation, see
ProxyBackend.java.
DN & Attribute RewritingAttributesRewritingSuppose you have a client application that expects a different
attribute name, such as fullname for a standard attribute
like cn (common name), and that expects a distinguished
name (DN) suffix different from what is stored in the directory. If you
cannot change the application, one possible alternative is a proxy layer
that does DN and attribute rewriting.Some servers, such as
OpenDJ directory server, can do attribute rewriting without a proxy layer.
See your directory server's documentation for details.
# A search accessing the directory server
$ ldapsearch -b dc=example,dc=com -p 1389 "(cn=Babs Jensen)" cndn: uid=bjensen,ou=People,dc=example,dc=com
cn: Barbara Jensen
cn: Babs Jensen
# The same search search accessing a proxy that rewrites requests and responses
$ ldapsearch -b o=example -p 8389 "(fullname=Babs Jensen)" fullnamedn: uid=bjensen,ou=People,o=example
fullname: Barbara Jensen
fullname: Babs JensenThe OpenDJ LDAP SDK RewriterProxy example builds on the Proxy example, rewriting requests
and search result entries. When you read the example, look for the
rewrite() methods.In the above output, the rewriter proxy listens on port 8389,
connecting to a directory server listening on 1389. The directory server
contains data from Example.ldif.