Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2014-10-10 04:52:18 +0000
committerJan Bartel2014-10-10 04:53:13 +0000
commitdd864f97996f8382b8e9f1044f3057fdfe3723f8 (patch)
tree372723ac70c3637298db19dc40a3fe98e7888f8c
parent6a0e220b9ccf499048ccb66a945f1bd64d0ca689 (diff)
downloadorg.eclipse.jetty.project-dd864f97996f8382b8e9f1044f3057fdfe3723f8.tar.gz
org.eclipse.jetty.project-dd864f97996f8382b8e9f1044f3057fdfe3723f8.tar.xz
org.eclipse.jetty.project-dd864f97996f8382b8e9f1044f3057fdfe3723f8.zip
443529 CrossOriginFilter does not accept wildcard for allowedHeaders
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java81
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java29
2 files changed, 86 insertions, 24 deletions
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
index ff790ade10..3d9f74d7f8 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.servlets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
@@ -64,7 +65,8 @@ import org.eclipse.jetty.util.log.Logger;
* <b>GET,POST,HEAD</b></li>
* <li><b>allowedHeaders</b>, a comma separated list of HTTP headers that
* are allowed to be specified when accessing the resources. Default value
- * is <b>X-Requested-With,Content-Type,Accept,Origin</b></li>
+ * is <b>X-Requested-With,Content-Type,Accept,Origin</b>. If the value is a single "*",
+ * this means that any headers will be accepted.</li>
* <li><b>preflightMaxAge</b>, the number of seconds that preflight requests
* can be cached by the client. Default value is <b>1800</b> seconds, or 30
* minutes</li>
@@ -119,8 +121,11 @@ public class CrossOriginFilter implements Filter
public static final String CHAIN_PREFLIGHT_PARAM = "chainPreflight";
private static final String ANY_ORIGIN = "*";
private static final List<String> SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
+ private static final List<String> DEFAULT_ALLOWED_METHODS = Arrays.asList("GET", "POST", "HEAD");
+ private static final List<String> DEFAULT_ALLOWED_HEADERS = Arrays.asList("X-Requested-With", "Content-Type", "Accept", "Origin");
private boolean anyOriginAllowed;
+ private boolean anyHeadersAllowed;
private List<String> allowedOrigins = new ArrayList<String>();
private List<String> allowedMethods = new ArrayList<String>();
private List<String> allowedHeaders = new ArrayList<String>();
@@ -155,13 +160,17 @@ public class CrossOriginFilter implements Filter
String allowedMethodsConfig = config.getInitParameter(ALLOWED_METHODS_PARAM);
if (allowedMethodsConfig == null)
- allowedMethodsConfig = "GET,POST,HEAD";
- allowedMethods.addAll(Arrays.asList(allowedMethodsConfig.split(",")));
+ allowedMethods.addAll(DEFAULT_ALLOWED_METHODS);
+ else
+ allowedMethods.addAll(Arrays.asList(allowedMethodsConfig.split(",")));
String allowedHeadersConfig = config.getInitParameter(ALLOWED_HEADERS_PARAM);
if (allowedHeadersConfig == null)
- allowedHeadersConfig = "X-Requested-With,Content-Type,Accept,Origin";
- allowedHeaders.addAll(Arrays.asList(allowedHeadersConfig.split(",")));
+ allowedHeaders.addAll(DEFAULT_ALLOWED_HEADERS);
+ else if ("*".equals(allowedHeadersConfig))
+ anyHeadersAllowed = true;
+ else
+ allowedHeaders.addAll(Arrays.asList(allowedHeadersConfig.split(",")));
String preflightMaxAgeConfig = config.getInitParameter(PREFLIGHT_MAX_AGE_PARAM);
if (preflightMaxAgeConfig == null)
@@ -353,9 +362,11 @@ public class CrossOriginFilter implements Filter
private void handlePreflightResponse(HttpServletRequest request, HttpServletResponse response, String origin)
{
boolean methodAllowed = isMethodAllowed(request);
+
if (!methodAllowed)
return;
- boolean headersAllowed = areHeadersAllowed(request);
+ List<String> headersRequested = getAccessControlRequestHeaders(request);
+ boolean headersAllowed = areHeadersAllowed(headersRequested);
if (!headersAllowed)
return;
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
@@ -367,7 +378,10 @@ public class CrossOriginFilter implements Filter
if (preflightMaxAge > 0)
response.setHeader(ACCESS_CONTROL_MAX_AGE_HEADER, String.valueOf(preflightMaxAge));
response.setHeader(ACCESS_CONTROL_ALLOW_METHODS_HEADER, commify(allowedMethods));
- response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, commify(allowedHeaders));
+ if (anyHeadersAllowed)
+ response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, commify(headersRequested));
+ else
+ response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, commify(allowedHeaders));
}
private boolean isMethodAllowed(HttpServletRequest request)
@@ -381,33 +395,52 @@ public class CrossOriginFilter implements Filter
return result;
}
- private boolean areHeadersAllowed(HttpServletRequest request)
+ List<String> getAccessControlRequestHeaders (HttpServletRequest request)
{
String accessControlRequestHeaders = request.getHeader(ACCESS_CONTROL_REQUEST_HEADERS_HEADER);
LOG.debug("{} is {}", ACCESS_CONTROL_REQUEST_HEADERS_HEADER, accessControlRequestHeaders);
+ if (accessControlRequestHeaders == null)
+ return Collections.emptyList();
+
+ List<String> requestedHeaders = new ArrayList<String>();
+ String[] headers = accessControlRequestHeaders.split(",");
+ for (String header : headers)
+ {
+ String h = header.trim();
+ if (h.length() > 0)
+ requestedHeaders.add(h);
+ }
+ return requestedHeaders;
+ }
+
+
+ private boolean areHeadersAllowed(List<String> requestedHeaders)
+ {
+ if (anyHeadersAllowed)
+ {
+ LOG.debug("Any header is allowed");
+ return true;
+ }
+
boolean result = true;
- if (accessControlRequestHeaders != null)
+ for (String requestedHeader:requestedHeaders)
{
- String[] headers = accessControlRequestHeaders.split(",");
- for (String header : headers)
- {
- boolean headerAllowed = false;
- for (String allowedHeader : allowedHeaders)
+ boolean headerAllowed = false;
+ for (String allowedHeader:allowedHeaders)
+ {
+ if (requestedHeader.equalsIgnoreCase(allowedHeader.trim()))
{
- if (header.trim().equalsIgnoreCase(allowedHeader.trim()))
- {
- headerAllowed = true;
- break;
- }
- }
- if (!headerAllowed)
- {
- result = false;
+ headerAllowed = true;
break;
}
}
+ if (!headerAllowed)
+ {
+ result = false;
+ break;
+ }
}
- LOG.debug("Headers [{}] are" + (result ? "" : " not") + " among allowed headers {}", accessControlRequestHeaders, allowedHeaders);
+ LOG.debug("Headers [{}] are" + (result ? "" : " not") + " among allowed headers {}", requestedHeaders, allowedHeaders);
return result;
}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
index 17916b395e..1d0df1bb9c 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
@@ -299,6 +299,35 @@ public class CrossOriginFilterTest
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
}
+
+ @Test
+ public void testPreflightWithWildcardCustomHeaders() throws Exception
+ {
+ FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
+ filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "*");
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
+
+ CountDownLatch latch = new CountDownLatch(1);
+ tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
+
+ String request = "" +
+ "OPTIONS / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Connection: close\r\n" +
+ CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS_HEADER + ": X-Foo-Bar\r\n" +
+ CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER + ": GET\r\n"+
+ "Origin: http://localhost\r\n" +
+ "\r\n";
+ String response = tester.getResponses(request);
+ Assert.assertTrue(response.contains("HTTP/1.1 200"));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_HEADERS_HEADER));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER));
+ Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
+ }
+
+
+
@Test
public void testPUTRequestWithPreflight() throws Exception
{

Back to the top