View Javadoc

1   package com.atlassian.plugins.rest.common.security.jersey;
2   
3   import com.atlassian.plugins.rest.common.security.XsrfCheckFailedException;
4   import com.sun.jersey.spi.container.ContainerRequest;
5   import com.sun.jersey.spi.container.ContainerRequestFilter;
6   import com.sun.jersey.spi.container.ContainerResponseFilter;
7   import com.sun.jersey.spi.container.ResourceFilter;
8   
9   import java.util.Arrays;
10  import java.util.HashSet;
11  import java.util.Locale;
12  import java.util.Set;
13  import javax.ws.rs.core.MediaType;
14  
15  /**
16   * A filter that filters requests that need XSRF protection.
17   * <p/>
18   * For now it only checks to see if there is a header.  Later when SAL has XSRF token support, maybe we can implement
19   * token checking.
20   *
21   * @since 2.4
22   */
23  public class XsrfResourceFilter implements ResourceFilter, ContainerRequestFilter
24  {
25      public static final String TOKEN_HEADER = "X-Atlassian-Token";
26      public static final String NO_CHECK = "nocheck";
27  
28      private static final Set<String> XSRFABLE_TYPES = new HashSet<String>(Arrays.asList(
29              MediaType.APPLICATION_FORM_URLENCODED, MediaType.MULTIPART_FORM_DATA, MediaType.TEXT_PLAIN
30      ));
31  
32      public ContainerRequest filter(final ContainerRequest request)
33      {
34          if (isXsrfable(request))
35          {
36              String header = request.getHeaderValue(TOKEN_HEADER);
37              if (header == null || !header.toLowerCase(Locale.ENGLISH).equals(NO_CHECK))
38              {
39                  throw new XsrfCheckFailedException();
40              }
41          }
42          return request;
43      }
44  
45      private boolean isXsrfable(ContainerRequest request)
46      {
47          String method = request.getMethod();
48          return method.equals("GET") || (method.equals("POST") && XSRFABLE_TYPES.contains(mediaTypeToString(request.getMediaType())));
49      }
50  
51      public ContainerRequestFilter getRequestFilter()
52      {
53          return this;
54      }
55  
56      public ContainerResponseFilter getResponseFilter()
57      {
58          return null;
59      }
60  
61      private static String mediaTypeToString(MediaType mediaType)
62      {
63          return mediaType.getType().toLowerCase(Locale.ENGLISH) + "/" + mediaType.getSubtype().toLowerCase(Locale.ENGLISH);
64      }
65  }