Extreme Java When vanilla Java is not enough


Tomcat manager with SSO and a different Realm

Tomcat Manager's default configuration isn't pratical (nor secure): you must store your users and passwords in a plain XML file. Of course, you can change the "<Realm>" definition on "<Engine name='Catalina'>", but it has no effect if you need a host with Single Sign On.

Since Manager needs to share the same host with managed applications, you need to create a context.xml for your Manager:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/manager" privileged="true">
  <Realm className="my.secure.and.custom.Realm"/>

Put it on "conf/<engine>/<host>/manager.xml". The "privileged='true'" will prevent a "java.lang.SecurityException: Servlet of class org.apache.catalina.manager.HTMLManagerServlet is privileged and cannot be loaded by this web application".

You must change "webapps/manager/WEB-INF/web.xml" and replace "<role-name>manager</role-name>" with the name of the role you want.


JAAS + Struts + Tomcat = Secure and pratical

Still working on the application I describe in my previous post, I started to integrate it to use JAAS. It is a Struts-based system running in a Tomcat server. The login was an Struts Action, and a RequestProcessor took care of redirecting to login page.

It was pretty easy the conversion to JAAS:

  1. I developed a new Realm for Tomcat. It was just a matter of extend the RealmBase class and override the authenticate method. This step could be skipped if my employer's LDAP server accepted anonymous search - JNDIRealm can do this job;
  2. With the Realm ready, add it to the application's context.xml (NetBeans users will find it inside META-INF folder of the project);
  3. Next step was to make a "public access" version of the application. Every code that does the authentication and authorization was removed, except the dynamic menu;
  4. The dynamic menu was changed to use the request.isUserInRole method. For some reason, this property can't be accessed by EL. I expected something like "request.userInRole['role']", but it didn't work;
  5. The logged user can be retrieved with either request.getUserPrincipal() or the EL "pageContext.request.userPrincipal";
  6. Now, it is just a matter of adding every Struts action to security constraints in web.xml. In NetBeans, it's an easy-to-use visual editor. Here is a snippet:
        <description>My secret pages</description>
        <description>Allowed roles</description>
  7. The login page, if using FORM-based authentication, is now something like:
    <form action="j_security_check" method="post">
      User: <input type="text" name="j_username"/>
      Password: <input type="password" name="j_password"/>
      <input type="submit" name="btLogin" value="login"/>
  8. To activate the FORM-based login, this must be added to web.xml:
  9. Did you notice the login error page is the same as the login page? To check if the user entered an invalid password, I use:
    <c:if test="${param.btLogin == 'login' and param.j_username <> ''}">
      <c:out value="Invalid username and/or password"/>

It is a long boilerplate, but steps are the same for every application. Using JAAS instead of programatic authorization makes your system more secure and easier to maintain.