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
17
18
19
20
21
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 }