Thursday, June 5, 2008

Configuring Tomcat to send P3P Compact Policy in HTTP response header

pencil icon, that"s clickable to start editing the post

Some time ago i did some analysis of P3P Compact Headers and the interplay it has with IE6+ to enable thirdparty cookies. The other day I assisted someone in implementing it in Tomcat. It was rather easy since the Servlet specfication has the filter feature that fits this like a glove.

Here's an example code for such a filter called StaticResponseHeaderFilter, that has been generalized to be able of appending any static HTTP header to the response. An important point is that I expect one policy to cover the hole site. I'm not sure if anyone differentiates the policy for different pages, though I guess it could in theory make sense, it could very easily confuse the users.

    1 package org.sweetxml.webutil;
    2 
    3 import java.io.IOException;
    4 
    5 import javax.servlet.Filter;
    6 import javax.servlet.FilterChain;
    7 import javax.servlet.FilterConfig;
    8 import javax.servlet.ServletException;
    9 import javax.servlet.ServletRequest;
   10 import javax.servlet.ServletResponse;
   11 import javax.servlet.http.HttpServletResponse;
   12 
   13 public class StaticResponseHeaderFilter implements Filter {
   14 
   15   private final static String HEADERNAME_INIT_PARAM = "headername";
   16   private final static String HEADERVALUE_INIT_PARAM = "headervalue";
   17 
   18 
   19   private String headername = null;
   20   private String headervalue = null;
   21 
   22 
   23   @Override
   24   public void init(FilterConfig filterConfig) throws ServletException {
   25     headername = filterConfig.getInitParameter(HEADERNAME_INIT_PARAM);
   26     headervalue = filterConfig.getInitParameter(HEADERVALUE_INIT_PARAM);
   27   }
   28 
   29   @Override
   30   public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
   31       ServletException {
   32 
   33     HttpServletResponse httpResp = (HttpServletResponse) response;
   34     // pass on to other filters or the resource
   35     filterChain.doFilter(request, response);
   36     // set HTTP header on response
   37     httpResp.setHeader(headername, headervalue);
   38   }
   39 
   40   @Override
   41   public void destroy() {
   42   }
   43 }

At first I had implemented it with ResponseWrapper, but as I thought of it I came to believe that it wasn't necessary (my experience with implementing filters are limited and when I'll need to use the wrapper classes).

It's configured like this in web.xml:

   39 
   40 
   41   <filter>
   42     <filter-name>StaticResponseHeaderFilter</filter-name>
   43     <filter-class>org.sweetxml.webutil.StaticResponseHeaderFilter</filter-class>
   44     <init-param>
   45       <param-name>headername</param-name>
   46       <param-value>P3P</param-value>
   47     </init-param>
   48     <init-param>
   49       <param-name>headervalue</param-name>
   50       <param-value>CP="CAO PSA OUR"</param-value>
   51     </init-param>
   52   </filter>
   53   <filter-mapping>
   54     <filter-name>StaticResponseHeaderFilter</filter-name>
   55     <url-pattern>/*</url-pattern>
   56   </filter-mapping>
   57 
   58 

And a quick check with wget gives:

wget -S http://localhost:8080/p3pdemo/
--23:20:08--  http://localhost:8080/p3pdemo/
Resolving localhost... ::1
Connecting to localhost|::1|:8080... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Server: Apache-Coyote/1.1
  Set-Cookie: JSESSIONID=8BFBF636E28A43E0F292345EAD7F6CB7; Path=/p3pdemo
  P3P: CP="CAO PSA OUR"
  Content-Type: text/html;charset=UTF-8
  Content-Length: 1609
  Date: Thu, 05 Jun 2008 21:20:08 GMT
  Connection: keep-alive
Length: 1609 (1.6K) [text/html]

Very easy indeed and the filter feature was just perfect.

As for implementing it in Apache HTTPD see the Appendix in The Platform for Privacy Preferences 1.0 Deployment Guide (W3C Note 11 February 2002) and for IIS

I can only conclude that the hardest part of implementing P3P is getting the policy right and being representative, it's not implementing it on servers.

2 comments :

Anonymous said...

Ah, if only it were so easy. The filter doesn't work on login, which is when you're sending the session cookie.

http://faq.javaranch.com/java/ServletsFaq#7

Sweetxml said...

Hi Jeremy

Thank you for pointing that out. I didn't know that tomcat doesn't invoke handlers when using Form-based authentication.

I haven't tried that out myself, but I guess that a workaround could be to handle session through URL's in the first step after authentication or swap to a handler-based login like SecurityFilter.

Best regards
Brian