

The purpose of the JNDIRealm implementation is to
provide a mechanism by which Tomcat can acquire information needed
to authenticate web application users, and define their security roles,
from a directory server or other service accessed via JNDI APIs. For
integration with Catalina, this class must implement the
org.apache.catalina.Realm interface.
This specification reflects a combination of functionality that is
already present in the org.apache.catalina.realm.JNDIRealm
class, as well as requirements for enhancements that have been
discussed. Where appropriate, requirements statements are marked
[Current] and [Requested] to distinguish them.
The current status of this functional specification is PROPOSED. It has not yet been discussed and agreed to on the TOMCAT-DEV mailing list.
The code in the current version of JNDIRealm, and the
ideas expressed in this functional specification, are the results of
contributions from many individuals, including (alphabetically):
The implementation of this functionality depends on the following external specifications:
The implementation of this functionality shall conform to the following requirements:
org.apache.catalina.Realm interface.
[Current]org.apache.catalina.Lifecycle
interface. [Current]org.apache.catalina.realm.RealmBase
base class.org.apache.catalina.realm package.
[Current]getContainer().log() method. [Current]The following environmental dependencies must be met in order for JNDIRealm to operate correctly:
$CATALINA_BASE/conf/server.xml, in a
<Realm> element that is nested inside a
corresponding <Engine>, <Host>,
or <Context> element.JNDIRealm by the appropriate Authenticator.
Correct operation of JNDIRealm depends on the following specific features of the surrounding container:
JNDIRealm will be initiated by
the appropriate Authenticator implementation, based
on the login method that is selected.The completed JNDIRealm must support two major operational
modes in order to support all of the required use cases. For the purposes
of this document, the modes are called administrator login and
Username Login. They are described further in the following
paragraphs.
For Administrator Login mode, JNDIRealm will be
configured to establish one or more connections (using a connection pool)
to an appropriate directory server, using JNDI APIs, under a "system
administrator" username and password. This is similar to the approach
normally used to configure JDBCRealm to access authentication
and access control information in a database. It is assumed that the
system administrator username and password that are configured provide
sufficient privileges within the directory server to read (but not modify)
the username, password, and assigned roles for each valid user of the
web application associated with this Realm. The password
can be stored in cleartext, or in one of the digested modes supported by
the org.apache.catalina.realm.RealmBase base class.
For Username Login mode, JNDIRealm does not
normally remain connected to the directory server. Instead, whenever a
user is to be authenticated, a connection to the directory server
(using the username and password received from the authenticator) is
attempted. If this connection is successful, the user is assumed to be
successfully authenticated. This connection is then utilized to read
the corresponding security roles associated with this user, and the
connection is then broken.
NOTE - Username Login mode cannot be used
if you have selected login method DIGEST in your web
application deployment descriptor (web.xml) file. This
restriction exists because the cleartext password is never available
to the container, so it is not possible to bind to the directory server
using the user's username and password.
Because these operational modes work so differently, the functionality for each mode will be described separately. Whether or not both modes are actually supported by a single class (versus a class per mode) is an implementation detail left to the designer.
NOTE - The current implementation only implements part of the Administrator Lookup mode requirements. It does not support the Username Lookup mode at all, at this point.
The implementation shall support the following properties that can be configured with JavaBeans property setters:
connectionURL - URL of the directory server we will
be contacting.contextFactory - Fully qualified class name of the JNDI
context factory used to retrieve our InitialContext.
[com.sun.jndi.ldap.LdapCtxFactory]The following processing must be performed when the start()
method is called:
The following processing must be performed when the stop()
method is called:
When authenticate() is called, the following processing
is required:
null.List of the security roles assigned to the
authenticated user.org.apache.catalina.realm.GenericPrincipal, passing as
constructor arguments: this realm instance, the authenticated
username, and a List of the security roles associated
with this user.GenericPrincipal objects for a particular user, because
the information in the directory server might have changed since the
last time this user was authenticated.GenericPrincipal.When hasRole() is called, the following processing
is required:
principal that is passed as an argument SHOULD
be one that we returned (instanceof class
org.apache.catalina.realm.GenericPrincipal, with a
realm property that is equal to our instance.principal meets these criteria, check
the specified role against the list returned by
getRoles(), and return true if the
specified role is included; otherwise, return false.principal does not meet these criteria,
return false.The implementation shall support the following properties that can be configured with JavaBeans property setters:
connectionURL - URL of the directory server we will
be contacting.contextFactory - Fully qualified class name of the JNDI
context factory used to retrieve our InitialContext.
[com.sun.jndi.ldap.LdapCtxFactory]The following processing must be performed when the start()
method is called:
The following processing must be performed when the stop()
method is called:
When authenticate() is called, the following processing
is required:
null.List of the security roles assigned to the
authenticated user.org.apache.catalina.realm.GenericPrincipal, passing as
constructor arguments: this realm instance, the authenticated
username, and a List of the security roles associated
with this user.GenericPrincipal objects for a particular user, because
the information in the directory server might have changed since the
last time this user was authenticated.GenericPrincipal.When hasRole() is called, the following processing
is required:
principal that is passed as an argument SHOULD
be one that we returned (instanceof class
org.apache.catalina.realm.GenericPrincipal, with a
realm property that is equal to our instance.principal meets these criteria, check
the specified role against the list returned by
getRoles(), and return true if the
specified role is included; otherwise, return false.principal does not meet these criteria,
return false.In addition to the assertions implied by the functionality requirements
listed above, the following additional assertions shall be tested to
validate the behavior of JNDIRealm: