JSP authentication can be managed by a servlet container such as Tomcat. The management of authentication and permissions is done by Tomcat. Your web application (your bundle of JSP and servlets) will not need to worry about this, all they need to do is choose which roles can access which pages. This is different to using sessions to keep track of logins like we did in PHP.
We can separate the authentication code and place that responsibility with Tomcat. The servlet specification has more information on container managed security. Individual JSP pages will not have to do any authorisation checking.
The web.xml
file, which is distributed as part of your web application, can specify restrictions on certain
pages to certain roles. Tomcat’s server.xml
is used to specify users that belong to roles. This means that if you
move your web application to another server (e.g. JRun) there is a different way to map users and roles.
The authentication can be setup in a number of ways, but the example below is using Tomcat and a PostgreSQL database.
Requirements
As part of our intranet web application there are some timesheet pages that reside in the timesheet/
directory.
Ideally, this part of the website should only be accessible by employees.
Choose a Role
The name of the role is simply employee
Create users and roles tables in PostgreSQL
Assume that the intranet
database has already been created.
bash-2.05a$ /usr/local/pgsql/bin/psql intranet
Password:
Welcome to psql 7.4.2, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
intranet=# CREATE TABLE users (
intranet(# username VARCHAR(15) NOT NULL PRIMARY KEY,
intranet(# password CHAR(32) NOT NULL
intranet(# );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users"
CREATE TABLE
intranet=# CREATE TABLE user_roles (
intranet(# username VARCHAR(15) NOT NULL,
intranet(# role VARCHAR(15) NOT NULL,
intranet(# PRIMARY KEY (username, role),
intranet(# FOREIGN KEY (username) REFERENCES users(username)
intranet(# );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "user_roles_pkey" for table "user_roles"
CREATE TABLE
Now insert an employee
intranet=# INSERT INTO users VALUES ('test', md5('test'));
INSERT 233820 1
And assign him the role of an employee.
intranet=# INSERT INTO user_roles VALUES ('test', 'employee');
INSERT 233821 1
You now have login, named test
with password test
inside this database.
Because this is a database, you can write frontends to manage this user list, or even have your web application maintain it.
Add JDBC drivers to Tomcat server.
It is not necessary to add drivers into the web application as the user and roles lookup is done by Tomcat, before a request reaches the web application.
So I copied the PostgreSQL drivers to $CATALINA_HOME</envar>/server/lib/postgresql.jar
. Tomcat will automatically
add all JAR files found here into its CLASSPATH
.
If the web application also wants to use a PostgreSQL database, then the drivers could’ve been placed into
$CATALINA_HOME</envar>/common/lib/
instead so they can all have access to it.
Modify Tomcat’s server.xml
This is Tomcat servlet container specific. Inside the Context of your web application, add the following elements
<Context path="/intranet" debug="0" privileged="true"
docBase="/home/aelst/intranet/web">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="localhost_intranet_log." suffix=".txt"
timestamp="true"/>
<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
driverName="org.postgresql.Driver"
connectionURL="jdbc:postgresql://localhost/intranet?user=dbuser&password=dbpass"
userTable="users" userNameCol="username" userCredCol="password"
userRoleTable="user_roles" roleNameCol="role"
digest="MD5"/>
</Context>
Note that we have added a logger for this web application, it helps us diagnose if something goes wrong.
The Realm element contains all the database information necessary for tomcat to connect to the database, and lookup the appropriate tables and columns to check the passwords. The digest attribute is set to MD5 as that is how the passwords are stored in this database.
Modify the web applications web.xml
The web.xml example below shows that the Timesheets section of the website, located in /timesheets/*
, can only be
accessed by users with the employee role. The web.xml
file is located in WEB-INF/
relative to the Context docBase.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<security-constraint>
<web-resource-collection>
<web-resource-name>Timesheets</web-resource-name>
<url-pattern>/timesheets/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>employee</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>employee</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
The authentication method of BASIC indicates it will use the browser’s default login prompt.
Links
The example web.xml
from the standard tomcat distribution is a well commented file.