JAAS + Struts + Tomcat = Secure and pratical
Wednesday, April 23rd, 2008Still 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:
- 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;
- With the Realm ready, add it to the application’s context.xml (NetBeans users will find it inside META-INF folder of the project);
- 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;
- 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;
- The logged user can be retrieved with either request.getUserPrincipal() or the EL “pageContext.request.userPrincipal”;
- 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:
<security-constraint> <web-resource-collection> <web-resource-name>SecurePages</web-resource-name> <description>My secret pages</description> <url-pattern>/secure.do</url-pattern> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <description>Allowed roles</description> <role-name>power_user</role-name> </auth-constraint> </security-constraint> - 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"/> </form>
- To activate the FORM-based login, this must be added to web.xml:
<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/login.jsp</form-error-page> </form-login-config> </login-config> - 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"/> </c:if>
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.