7.12 Securing Cactus Tests

7.12.1 Problem

You want to test a servlet that depends on an authenticated user.

7.12.2 Solution

Configure your web application to handle BASIC authentication and use Cactus to automatically create an authenticated user.

7.12.3 Discussion

Testing server-side code is challenging by itself. Throw in server-side code that relies on an authenticated user, and the challenge grows. Cactus provides a way to test server-side code that relies on an authenticated userby creating a user for you.[10]

[10] Cactus 1.4 only supports BASIC authentication.

If your servlet or filter uses the following methods then you need Cactus to create an authenticated user:

  • HttpServletRequest.getRemoteUser( )

  • HttpServletRequest.getUserPrincipal( )

  • HttpServletRequest.isUserInRole(String)

If your web application requires an authenticated user, your web application must be secured. In the deployment descriptor, you must declare the URL patterns to secure and which logical roles are allowed. Example 7-15 shows how this is done.

Example 7-15. Securing a web application
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
 
  <!-- other elements left out for brevity -->

  <!-- URL pattern not secured -->
  <filter>
      <filter-name>FilterRedirector</filter-name>
      <filter-class>
        org.apache.cactus.server.FilterTestRedirector
      </filter-class>
  </filter>

  <!-- URL pattern secured -->
  <filter>
      <filter-name>SecureFilterRedirector</filter-name>
      <filter-class>
        org.apache.cactus.server.FilterTestRedirector
      </filter-class>
  </filter>  
  <filter-mapping>
    <filter-name>SecureFilterRedirector</filter-name>
    <url-pattern>/SecureFilterRedirector</url-pattern>
  </filter-mapping>

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>SecurityRestriction</web-resource-name>
      <url-pattern>/SecureFilterRedirector</url-pattern>
      <http-method>POST</http-method>
      <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>filterTest</role-name>
    </auth-constraint>
  </security-constraint>

  <login-config>
    <auth-method>BASIC</auth-method>
  </login-config>
  <security-role>
    <role-name>filterTest</role-name>
  </security-role>
</web-app>

The example above can be applied to any URL pattern, not just filters. For instance, if you want to secure access to a servlet or JSP, simply add more url-pattern elements. The role name is a logical role that is mapped to one or more users. An underlying authorization mechanism defines how role names are mapped. Tomcat, by default, uses the TOMCAT_HOME/conf/tomcat-users.xml file to define users and their roles. This is not a very strong authentication and authorization mechanism but does provide a convenient and easy means to run our tests. Here's an example showing how to add a new user and role to the tomcat-users.xml file:

<tomcat-users>
  <user name="javaxp" password="secret" roles="manager"/>
  <user name="coyner_b" password="secret" roles="filterTest"/>
</tomcat-users>

Notice that the filterTest role matches the role name in the deployment descriptor. Example 7-16 shows how to set up a test method to provide an authenticated user. The beginAuthenticatedUser(WebRequest) method is accompanied by a test method called testAuthenticatedUser( )not shown here. The WebRequest object allows for the redirector to be specified before executing the server side test. Recall that Cactus uses a cactus.properties file to set up redirectors for each Cactus test case. The values in the properties file are simply the URL patterns defined in the deployment descriptor. Thus, setting the redirector name programmatically simply changes the URL pattern. This provides ultimate flexibility because multiple test methods can be tested using a secured or nonsecured URL, where a secured URL requires an authenticated user.

Example 7-16. Setting up an authenticated user
public void beginAuthenticatedUser(WebRequest webRequest) {
    webRequest.setRedirectorName("SecureFilterRedirector");
    webRequest.setAuthentication(
            new BasicAuthentication("coyner_b", "secret"));
}

7.12.4 See Also

Recipe 7.11 shows how to test servlet filters.