Extreme Java When vanilla Java is not enough

17Mar/090

JAAS and Filters

Small tip of the day. If you define a servlet filter and container managed security on the same application, keep these in mind:

  • If your filter is "url-mapped", it is executed BEFORE the security manager;
  • If it is "servlet-mapped", it is executed AFTER the security manager.

I tested it when developing a filter to handle "user life cycle" (expired passwords, agreement signing, etc). If I map both filter and security to "/*", filter was run. If I map security to "/*" and filter to "Faces Servlet", it is not executed until authenticated (even when accessing "/faces/index.jsp").

Tagged as: , , No Comments
23Apr/080

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:
    <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>
  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"/>
    </form>
  8. 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>
  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"/>
    </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.