JDBCRealm

Table of Contents

Overview

Introduction

The purpose of the JDBCRealm 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 relational database accessed via JDBC APIs. For integration with Catalina, the resulting class(es) 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.JDBCRealm 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.

External Specifications

The implementation of this functionality depends on the following external specifications:

Implementation Requirements

The implementation of this functionality shall conform to the following requirements:

  • Be realized in one or more implementation classes.
  • Implement the org.apache.catalina.Realm interface. [Current]
  • Implement the org.apache.catalina.Lifecycle interface. [Current]
  • Subclass the org.apache.catalina.realm.RealmBase base class.
  • Live in the org.apache.catalina.realm package. [Current]
  • Support a configurable debugging detail level. [Current]
  • Log debugging and operational messages (suitably internationalized) via the getContainer().log() method. [Current]

Dependencies

Environmental Dependencies

The following environmental dependencies must be met in order for JDBCRealm to operate correctly:

  • The desire to utilize JDBCRealm must be registered in $CATALINA_BASE/conf/server.xml, in a <Realm> element that is nested inside a corresponding <Engine>, <Host>, or <Context> element.

Container Dependencies

Correct operation of JDBCRealm depends on the following specific features of the surrounding container:

  • Interactions with JDBCRealm will be initiated by the appropriate Authenticator implementation, based on the login method that is selected.
  • JDBCRealm must have the JDBC standard API classes available to it. For a JDK 1.2 or later container, these APIs are included in the standard platform.
  • When connection pooling is implemented, JDBCRealm must have the JDBC Optional Package (version 2.0 or later) APIs available to it. This library is available as a separate download (and will be included in Tomcat binary distributions).

Functionality

Overview of Operation

The main purpose of JDBCRealm is to allow Catalina to authenticate users, and look up the corresponding security roles, from the information found in a relational database accessed via JDBC APIs. For maximum flexibility, the details of how this is done (for example, the names of the required tables and columns) should be configurable.

Each time that Catalina needs to authenticate a user, it will call the authenticate() method of this Realm implementation, passing the username and password that were specified by the user. If we find the user in the database (and match on the password), we accumulate all of the security roles that are defined for this user, and create a new GenericPrincipal object to be returned. If the user is not authenticated, we return null instead. The GenericUser object caches the set of security roles that were owned by this user at the time of authentication, so that calls to isUserInRole() can be answered without going back to the database every time.

Detailed Functional Requirements

Configurable Properties

The implementation shall support the following properties that can be configured with JavaBeans property setters:

  • Configuration parameters defining the JDBC driver to use, the database connection URL to be accessed, and the username/password to use for logging in. [Current]
  • Configuration parameters describing the connection pool to be created to support simultaneous authentications. [Requested]
  • Name of the tables to be searched for users and roles. [Current]
  • Name of the columns to be used for usernames, passwords, and role names. [Current]

Lifecycle Functionality

The following processing must be performed when the start() method is called:

  • Establish a connection to the configured database, using the configured username and password. [Current]
  • Configure and establish a connection pool of connections to the database. [Requested]

The following processing must be performed when the stop() method is called:

  • Close any opened connections to the database.

Method authenticate() Functionality

When authenticate() is called, the following processing is required:

  • Acquire the one and only connection [Current] or acquire a connection from the connection pool [Requested].
  • Select the one and only row from the user's table for this user, and retrieve the corresponding password column. If zero rows (or more than one row) are found, return null.
  • Authenticate the user by comparing the (possibly encrypted) password value that was received against the password presented by the user. If there is no match, return null.
  • Acquire a List of the security roles assigned to the authenticated user by selecting from the roles table.
  • Construct a new instance of class 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.
  • WARNING - Do not attempt to cache and reuse previous GenericPrincipal objects for a particular user, because the information in the directory server might have changed since the last time this user was authenticated.
  • Return the newly constructed GenericPrincipal.

Method hasRole() Functionality

When hasRole() is called, the following processing is required:

  • The 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.
  • If the passed 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.
  • If the passed principal does not meet these criteria, return false.

Testable Assertions

In addition to the assertions implied by the functionality requirements listed above, the following additional assertions shall be tested to validate the behavior of JDBCRealm:

Comments

Notice: This comments section collects your suggestions on improving documentation for Apache Tomcat.

If you have trouble and need help, read Find Help page and ask your question on the tomcat-users mailing list. Do not ask such questions here. This is not a Q&A section.