Wednesday, September 21, 2011

Tomcat - using Realm to protect access to JSF application (part 2 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 2.1.7
 
Requirements:
  • understanding basics of Tomcat's Realm
You will learn:
  • how to define users and roles in own web applications (JSF 2.0 as example)
  • how to use encrypted passwords for realm users instead od plain text
In the previous post I described how to configure access to Tomcat's server administration application using Tomcat's Realm elements. The whole thing boiled down to write a few lines of text in server.xml file. But how does it look like when we have to do it from scratch in our application?

Step 1. Let's create very simple JSF application which has only 3 pages:
  • /index.html - main page with two buttons navigating into two pages:
  • /unrestrictedPage.xhtml - page always accessible and visible to anyone
  • /restricted/restrictedPage.xhtml - page and directory available only for valid users
The complete application structure will look like:



Step 2: we have to add a privilleged user named admin with password adminpass who belongs to role privillegedUsers (You can choose any user login, password and role name). Just simply add this line:
<user username="admin" password="adminpass" roles="privillegedUsers" />
into [tomcat directory]\conf\tomcat-users.xml file.

Step 3: configuring application. We have to modify web.xml of our sample application by adding following text:
<web-app>
...
    <security-role>
        <description>
              All persons belong to that role have access to restricted application area.
        </description>
        <role-name>privillegedUsers</role-name>
    </security-role>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Restricted</web-resource-name>
            <url-pattern>/faces/restricted/*</url-pattern>
            <url-pattern>/restricted/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>privillegedUsers</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Restricted access</realm-name>
    </login-config>
...
</web-app>
First we defined a role named privillegedUsers - the same we put in tomcat-users.xml file above. Second we have to defined prottected parts of our application, by providing proper URL pattern. Please note that we have two entries here: /restricted/* - everything in this directory is protected in case someone typed this part manually in browser's address bar,  /faces/restricted/* - JSF adds "faces" prefix when navigating between pages, so the URL is a little bit different and we have to watch for this also. After that we have to define a role which is allowed to access to the protected parts. This is privillegedUsers role defined earlier. At the end we have to define the way how the authentication is done - the simplest way is BASIC, which displays predefined form with credentials.

Now we are ready to deploy our application on Tomcat and run it. It should look like this:


when we try to access to restricted area. In order to do this we have to put credentials for user defined in step 2 (admin, adminpass).

Note: there is a little trick here, for the button "Restricted area" - see index.xhtml page source code:
<h:commandButton value="Resricted area" action="/restricted/restrictedPage.xhtml?faces-redirect=true" />
<h:commandButton value="Unrestricted area" action="/unrestrictedPage.xhtml" />
Because JSF internally by default makes forward to other page, browser is unaware what has happened and display URL from one step back. In such case our URL security patterns will not match anything, and restrictedPage.xhtml will be displayed without asking for login and password! In order to make protection work we have to perform full redirection for that action in order to force browser to fetch target URL and display it. For JSF applications it is better to use filters or Spring Security in order to avoid such dirty tricks.

Encrypted passwords.

As You probably have seen, passwords vor valid users are stored inside tomcat-users.xml file as a plain text. There is a possibility to store them in encrypted form, using MD5. Here is what needs to be done:

Step 1: using Eclipse modify Tomcat server.xml and its <Realm> atrribute into:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" digest="MD5"/>
Step 2: in web.xml change <auth-method> from BASIC to DIGEST

Step 3: for user admin and his previous password adminpass we have to generate its md5 equivalent using Tomcat's digest.bat file (located in [tomcat directory]\bin folder) :

digest.bat -a md5 admin:"Restricted access":adminpass

"Restricted access" is a realm name taken from <auth-method> tag from web.xml. Those names must match, if name contains spaces, it must be surrounded with "".


Step 4: using Eclipse modify Tomcat's tomcat-users.xml file:
<user username="admin" password="db7bc05adcf611fc779f32a4e680cc01" roles="privillegedUsers" /> 
where password was taken as a result of executing command from step 3.

-------------------------------------------
Download source files:

Note: make sure that Java, Eclipse and Tomcat are properly installed and configured for running the project (additional configuration may be required if different directories are used).

Eclipse complete sample project is here (with all required libraries).

Tuesday, September 13, 2011

Tomcat - change default application, protecting access to web applications using Realm (part 1 of 2)

Note: below description uses Eclipse Indigo, Tomcat 7.0.28,

Requirements:
  • installed Java (description here)
  • installed and configured Eclipse (description here)
  • installed and confiured Tomcat for the Eclipse (description here)
You will learn:
  • how to change default Tomcat application
  • how to allow users access to Tomcat's server administration application using Tomcat's Realm

Let's assume that You have Tomcat which is configured to work in Eclipse. When You start Tomcat (using Eclipse or standard scripts from Tomcat's distribution) and type in the browser URL http://localhost:8080, You will see Tomcat's default application:


This application is located in the [tomcat directory]\webapps\ROOT folder. If You want to change this page, just edit content of file index.jsp and index.html. If You want to completely remove this application, just remove complete ROOT folder.
Removing is not the best choice, because Tomcat is shipped with a special applications for server administration. You can access those applications using links in red square. Try to click on any link - You should see screen with login and password prompt:


Those parts are protected using Tomcat Realm. What is Realm? Realm is a set of valid users (defined by user name and password) and roles where those users belong. The idea is to configure access to web application only for valid users from certain roles. But where are those users and roles stored? It depends on a implementation of a realm - they can be stored in database, in LDAP, or in xml file. Tomcat's server administration application uses xml file to define users' access. Let's try to set up some users able to start that application.

Step 1: using Eclipse open server.xml from the Servers, and make sure that entry <Realm classname="org.apache.catalina.realm.UserDatabaseRealm" resourcename="UserDatabase"></Realm> exsits between <Engine> tags, outside <Host&gt tags - it means that this realm will be used for all hosts and all applications on that  hosts:


Step 2: using Eclipse open tomcat-users.xml from the Servers and add an entry for the user who will be able to access Tomcat's server administration application:


By default UserDatabaseRealm uses [tomcat directory]\conf\tomcat-users.xml file to load users and their roles into memory on server startup. In order to allow defined users to access administration application, they need to belong to roles named manager-status, manager-gui and admin-gui. After changes made, restart Tomcat server and try to access Tomcat's administration application giving username and password from tomcat-users.xml file. If everything was set up OK, You should see mentioned applications.

You may wonder why we used here roles named manager-status or manager-gui or admin-gui. Those role names come from Tomcat's server administration application specific settings, stored in the web.xml file. In the next post I will show how to protect own application (JSF2 application will be used as an example) and how to define own roles.