The tomcat memory realm example (contained in package org.apache.catalina.realm.MemoryRealm) uses an in-memory user database, which is read from an XML file on server startup. The root of the XML structure is the <tomcat-users> element, which holds the <user> elements. Each <user> element contains the required attributes for each user – name (username for authentication), password (plain text password), and roles (comma-separated list of roles that the user belongs to, used for authorization).
Below is an example XML Defining Four Users, with Usernames, Passwords, and User Roles.
<tomcat-users> <user name="tomcat" password="tomcat" roles="tomcat" /> <user name="role1" password="tomcat" roles="role1" /> <user name="both" password="tomcat" roles="tomcat,role1" /> <user name="eric" password="password" roles="tomcatuser" /> </tomcat-users>
Most user definitions are simple, with username, password, and a single role, but one common scenario involves users that have two or more roles, which can be specified as comma-separated values in XML.
Below steps can be done to secure access to a web application
To actually see how a MemoryRealm works, let’s create a realm that protects our web application context-root /cavalry. The first step is to enable MemoryRealm in the Tomcat configuration file CATALINA_HOME/conf/server.xml. All we need to do to achieve this is to add the following line under the <Engine>, <Host>, or <Context> element of server.xml. We will configure it for our /cavalry web application under <Context> element as below
Tomcat memory realm example Configuration in server.xml file
<Context path="/cavalry" docBase="cavalry"> <Realm className="org.apache.catalina.realm.MemoryRealm" /> </Context>
If the <Realm> element is added under the <Engine> element of server.xml, all web applications served by the engine will have the realm enabled. That usually means that all web applications deployed on the Tomcat instance can use the configured realm. If the <Realm> element is within the <Host> element, all web applications within that host will have the realm enabled, but the web applications belonging to other hosts defined won’t see the realm at all. Finally, if the <Realm> element is within the <Context> XML element, only web applications that are defined for that context can use the configured realm.
Only one realm is active for each web application at any given time. Therefore, the realm defined in <Engine> will apply to all web applications deployed on the server, unless it’s overridden by the <Realm> element under <Host>. Similarly, a realm defined under the <Engine> or <Host> elements can be overridden by a single web application-configured realm, under <Context> element. To avoid confusion and to keep configuration as robust as possible, it is a recommended approach to configure a realm on the web application level, within <Context> element.
However, just configuring the realm in this way won’t make the web application secure; adding the <Realm> element to server.xml simply enables the realm for the web application. The web application must also be configured to use the realm’s security features to complete the configuration. You can test this by starting the Tomcat server after this change is made and trying to access /examples, /cavalry, or any other application deployed – all of them will still be accessible as before, without any username or password required.
The next step is to configure the /cavalry sample web application to use the configured MemoryRealm implementation by editing web.xml file for our web application (located in CATALINA_HOME/webapps/cavalry/WEB-INF/web.xml). We need to add the <security-constraint> element to the web.xml, and define the protected resource.
Definition of a Secured Resource in web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Cavalry</display-name> <description>Security Realms Demo</description> <security-constraint> <web-resource-collection> <web-resource-name>Memory Realm Sample</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>tomcatuser</role-name> </auth-constraint> </security-constraint> </web-app>
First, we define the <security-constraint> element, which acts as a holder for all security configurations for this web application. This element has two required child elements: <web-resourcecollection>, which defines the URL path of the web applications that are to be protected, and <auth-constraint>, which defines authorization roles that a user accessing the protected URLs must have.
Within the <web-resource-collection> element we define its name and the URL pattern that matches all web application URLs that we want to protect. It this example, we want to protect all pages of our sample application, so we use the wildcard character to match all URLs (/*). As for the authorization part, we set the role name that is required for the access pages specified – the role name is “tomcatuser.” you will notice that we have configured user “eric” to have role “tomcatuser.”
If you now restart Tomcat and navigate to our web application’s home page (http://localhost:8080/cavalry/jsps/index.jsp), you will see an error page with HTML status code 403 Forbidden – which means that access to the page is restricted successfully.
So we have secured our web application, but when we tried to access it, we got the error page straight away. We should be offered a chance to enter a username and password and, if we log in successfully and have the required role, we should see the actual page. The configuration so far only protected the page – we need a few more lines of XML code in order to tell Tomcat to render a login page if a user is not logged in.
For that, we are going to add the <login-config> element to web.xml file, after the <securityconstraint> element. Below example shows the additional configuration we need to add to the web.xml file of our web application.
<login-config> <auth-method>BASIC</auth-method> <realm-name>CavalryRM</realm-name> </login-config>
For login configuration, we need to set the authentication method to use. For this example, we will use basic authentication supported by Tomcat. With basic authentication, the server will display a popup window when you try to access a secure resource. In this window, you can type a username and password. The username and password are then transported (in plain text) to the Tomcat’s built-in authentication mechanism, which will check your credentials against a configured user database (in our case, tomcat-users.xml file, as defined by MemoryRealm). We also configure the authentication realm name, which will be displayed in the login window.
In addition to BASIC authentication, Tomcat supports other types of authentication: FORM, DIGEST, and CLIENT_CERT. FORM authentication.
BASIC : Client authenticates by entering a username and password to a built-in browser login window. The browser sends the username and password in HTTP header in plain text, Base64 encoded. The username and password are then decoded on the server.
FORM : This is the most common authentication type. Client authenticates using HTML form by entering a username and password. The sending mechanism, password encoding, and the style of the HTML form are customizable by the user. The form attributes (input field names and form action attributes) are defined as part of Java Servlet specification.
DIGEST : Similarly to BASIC authentication, this uses the browser’s login window to collect credential details and send them to the server as HTTP header. Unlike with BASIC authentication, usernames and passwords are digested – encoded using MD5 algorithm, which is a one-way hash function, so the username and password cannot be decoded – making authentication more secure. Some older browsers do not support DIGEST authentication.
CLIENT_CERT : This authentication type uses Secure Socket Layer (SSL), where both the client (user) and the server have their own SSL certificates, which are used for mutual authentication. This type of authentication does not require a username and password, and is the most secure of all the types mentioned.
After finishing with the configuration, you’ll have to restart Tomcat in order to apply the changes. After you restart, navigate the browser to the same URL as before (http://localhost:8080/cavalry/jsps/index.jsp), and you will see a login window displayed, asking you to enter your username and password.
If you enter a username or password that is not contained in the tomcat-users.xml file, you will see the login dialog displayed again. This will repeat until you enter a valid username and password. Tomcat handles the flow of BASIC authentication process, and displays the login prompt until the correct details are entered; there is no special configuration for this functionality. Now enter the username and password of the user that has required role “tomcatuser” – which is our user “eric” with password “password” – and you will be presented with our sample web application home page.