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.
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 accessable by employees.
The name of the role is simply 'employee'
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.
It is not necessary to add the the drivers into the web application as the user and roles lookup is done by Tomcat, before it even reaches the web application.
So I copied the PostgreSQL drivers to $CATALINA_HOME/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/common/lib/ instead so they can all have access to it.
This is Tomcat servelet 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.
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.