Authentication with Apache Tomcat by using a valve
Algemeen
By using the standard J2EE-authentication process the user has to reconnect to the application every time when he/she starts a new session or starts the browser again (Basic Authorization). This is not userfriendly within the most companies where there are lot of applications running and it's not logical to have a username/password combination for every application. Apache Tomcat offers a solution for this which is the implementation of Realms and Valves.
A Realm is a pool of valid users with passwords for different web applications. Within a Realm there is also a relation between the users and the roles with each valid user available. A role gives the valid users privilege to access different parts of a webapplication.
A Tomcat valve allows you to associate an instance of a Java class with a particular Catalina container. A valve works the same as a standard J2EE servlet filter. But you can access specific internal Tomcat information. This gives you more options, but has the disadvantage that they are specific to the Tomcat web container. You could use valves for authorization, logging. The conclusion is that Valves are an Apache Tomcat specific alternative for filters.
Within WTell the application makes use of a JDBCRealm and a custom Valve for making easy logging in possible. Using the JDBCRealm is good documented at the
Apache Tomcat website. The source of the JDBCRealm could be the list of users within a table of the linked ERP-package or just a separate user table. The configuration of the valve is documented in this manual.
Within WTell the valve is implemented differently and more secure, but the use of this manual is to give an impression how the valve could be implemented.
Version Control
| Version | Date | Adjustments |
| 1.0. | 16-mrt-2009 | First version |
Version control
Manual
This manual consists of two parts. In the first part the source code of the valve will be explained and in the second part the adjustments of server.xml will be shown. The sourcecode of the valve is split in three parts which will be explained part by part. In the first part of the sourcecode the needed imports are shown.
- General creation of the valve
- Setting a principal
- Finding a cookie with a username
- Adjusting server.xml
General creation of the valve
 |
| Authentication valve part 1 |
Important in this part is that it's wise to extend the org.apache.catalina.valves.ValveBase by creating a custom valve, because this class has al the needed general methods implemented where you only have to implement the method
public void invoke(Request request, Response response) throws IOException, ServletException {}
Also you should complete your valve with the following this.getNext().invoke(request,response). This is needed for calling the next valve or giving the request response to the next filter, servlet in the process. If you don't do this then the processing of the request and response will stop. You can compare this functionality by using chain.doFilter(Request,Response) within a Filter.
In line 24 the org.apache.catalina.session is returned by calling the method request.getSessionInternal(). This object is needed for determining if there is a Principal related to a session. A principal is an abstract identity within Java, which could be used to represent an individual, a enterprise, or a login id. Within this example it's a login id. If there is no principal related to this session then the Principal is null and the code has to create one if possible. The class Authenticator tries to create a Principal from a cookie and the username of the cookie is gathered by using the method getLogin(request). If no cookie with a username is found the next valve will be called which will start the login screen for the user depending on the configured method within the login-config element of the web.xml within the webapplication
Setting a principal
 |
| Authentication valve part 2 |
If a cookie with a username is found then a list of roles of this user has to be determined. This is done at line 35 with the statement Roles.getRolesFromUser(strUser). This line of code gathers the related roles of the user from the database and because of this it could throw a SQLException which is rethrown as a ServletException.
When the roles of the user is known then a new GenericPrincipal is created at line 40 from the given values. After the creation of this Principal it will be added to the request and the session for further requests (lines 42,43).
When a principal is succesfully related to a usersession and the attribute checked is not set then there will be a new Cookie created at line 47. The path of this cookie is set to "/" so that all applications within Apache Tomcat share the same cookie. This new cookie is added to the response object and also the attribute checked will be set which makes sure that during the usersession the cookie is not set again.
In line 53 the next valve will be called by the statement this.getNext().invoke(request,response)
Finding a cookie with a username
 |
| Authentication valve part 3 |
At line 58 there is a static method for determining the related cookie within the request. In line 60 all the related cookies of the request are gathered by request.getCookies(); All the cookies are checked by a for loop and when the cookie with the name WTuser is found the value is returned (line 64). If there is no cookie with the needed name then "" is returned (line 68).
Adjusting server.xml
After the creation of the valve the server.xml file within Apache Tomcat should be changed so that the valve is in use.
This file can be found at the conf-directory.of the Apache Tomcat installation. Relate the valve by the standard valve for SingleSignOn which will change the server.xml like the underlying picture
 |
| Server.xml Apache Tomcat |
Now you can restart Apache Tomcat and the new valve is in use.