Tutorial: Authentication with Tomcat 6 using JNDI DataSourceRealm
This article is a tutorial about how to implement an authentication mechanism in Apache Tomcat 6 by using a JNDI datasource for looking up users, their passwords and roles. It shows how to prepare Tomcat 6 for using a so called DataSourceRealm and describes how web applications can be secured by a security realm. The illustrated examples use HTTP Basic Authentication.
Must knows
Apache Tomcat’s realms are not more than databases which store usernames, passwords and associated roles. Realms are managed through Tomcats context, not through custom application contexts. Because Tomcat manages those realms, they have to be configured within Tomcat’s configuration files. But if you want to secure your custom application from unwanted users, you have to prepare your application and command it to use authentication. That is want we are going to do now.
Preparing the application
To command your application to check the requestor’s authenticity, you have to add several areas to your applications deployment descriptor web.xml. First, lets start by telling our webapp which authentication method has to be used and name your security realm. Put the following snippet into your web.xml under the <web-app>-tag.
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>My secure realm</realm-name>
</login-config>
This configuration says, that HTTP Basic Authentication method is used to secure the given realm. Besides HTTP Basic (named BASIC), it is possible to use other methods. The possible ones are as following:
- BASIC: HTTP Basic
- CLIENT-CERT: HTTPS
- FORM: HTML form based
So according this list, you could also define the following login configurations.
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>My secure realm</realm-name>
</login-config>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>My secure realm</realm-name>
</login-config>
Now, we have to define the security roles, our application requires. In my example, I called it just STANDARD.
<security-role>
<role-name>STANDARD</role-name>
</security-role>
At last, we have to add a constraint to our application’s web.xml, telling it, that accessing each resource matching a given URL pattern requires the previously defined role STANDARD.
<security-constraint>
<web-resource-collection>
<web-resource-name>My secure resource</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>STANDARD</role-name>
</auth-constraint>
</security-constraint>
Preparing Tomcat
Now, we will introduce Tomcat to another realm, actually a DataSourceRealm, by inserting the following snippet into its server.xml under the <Engine> -tag.
<Realm className="org.apache.catalina.realm.DataSourceRealm"
dataSourceName="jdbc/authDB"
roleNameCol="rolename"
userCredCol="password"
userNameCol="username"
userRoleTable="ref_user_account_role"
userTable="ref_user_account" />
As shown in the previous snippet, we told this realm to use a JNDI resource named jdbc/authDB. To make this datasource accessible, we have to define in Tomcat’s server.xml under the <GlobalNamingResources>-tag as follows. I used a PostgreSQL datasource in this example.
<Resource name="jdbc/authDB" auth="Container"
driverClassName="org.postgresql.Driver"
type="javax.sql.DataSource"
url="jdbc:postgresql://localhost:5432/auth"
username="username" password="password"
maxActive="50" maxIdle="1" maxWait="10000"
removeAbandoned="true"
removeAbandonedTimeout="30"/>
We have now prepared Tomcat and our webapp, to use authentication. What is left to do, is to create the database structures and especially the needed users and roles.
The realm itself
To make the authentication mechanism finally work, just the creation of the database structures according the defined criterias (such as the username, password and database name defined in the JDBC JNDI resource in server.xml) has to be done. The following table definitions show, which tables have to be provided in this context to make the example work.
CREATE TABLE ref_user_account
(
username character varying(12) NOT NULL,
"password" character varying NOT NULL,
CONSTRAINT pk_user_account PRIMARY KEY (username)
)
CREATE TABLE ref_user_role
(
rolename character varying(12) NOT NULL,
CONSTRAINT pk_user_role PRIMARY KEY (rolename)
)
CREATE TABLE ref_user_account_role
(
username character(12) NOT NULL,
rolename character varying(12) NOT NULL,
CONSTRAINT pk_user_account_role PRIMARY KEY (username, rolename),
CONSTRAINT fk_user_account_role_rolename FOREIGN KEY (rolename)
REFERENCES ref_user_role (rolename) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk_user_account_role_username FOREIGN KEY (username)
REFERENCES ref_user_account (username) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
As you can see, the table names and the column names match the defined ones in the server.xml’s realm definition. So now, just add the needed users and roles.
--The STANDARD role
INSERT INTO ref_user_role (rolename) VALUES ('STANDARD');
--A sample user named otto
INSERT INTO ref_user_account (username, password) VALUES ('otto', 'otto');
INSERT INTO ref_user_account_role (username, rolename) VALUES ('otto', 'STANDARD');
If you will now redeploy your webapp and the to reqest a resource, you will be asked to enter a username and password via HTTP Basic to access. You should be shown a dialog equal to this one. Try typing the username ‘otto’ with the password ‘otto’ to continue ![]()

References and resources
- Understanding Web Security Using web.xml Via Use Cases | Javalobby
- Apache Tomcat 6.0 | Realm Configuration HOW-TO
