366472: CrossDomainFilter accepts wildcard domains like *.example.com
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
cf30b19f7e
commit
30dade6b5a
|
@ -18,6 +18,8 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
|
@ -229,19 +231,34 @@ public class CrossOriginFilter implements Filter
|
||||||
if (origin.trim().length() == 0)
|
if (origin.trim().length() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
boolean allowed = false;
|
|
||||||
for (String allowedOrigin : allowedOrigins)
|
for (String allowedOrigin : allowedOrigins)
|
||||||
{
|
{
|
||||||
if (allowedOrigin.equals(origin))
|
if (allowedOrigin.contains("*"))
|
||||||
{
|
{
|
||||||
allowed = true;
|
Matcher matcher = createMatcher(origin,allowedOrigin);
|
||||||
break;
|
if (matcher.matches())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (allowedOrigin.equals(origin))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allowed)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
private Matcher createMatcher(String origin, String allowedOrigin)
|
||||||
|
{
|
||||||
|
String regex = parseAllowedWildcardOriginToRegex(allowedOrigin);
|
||||||
|
Pattern pattern = Pattern.compile(regex);
|
||||||
|
return pattern.matcher(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseAllowedWildcardOriginToRegex(String allowedOrigin)
|
||||||
|
{
|
||||||
|
String regex = allowedOrigin.replace(".","\\.");
|
||||||
|
return regex.replace("*",".*"); // we want to be greedy here to match multiple subdomains, thus we use .*
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSimpleRequest(HttpServletRequest request)
|
private boolean isSimpleRequest(HttpServletRequest request)
|
||||||
|
|
|
@ -76,6 +76,52 @@ public class CrossOriginFilterTest
|
||||||
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleRequestWithMatchingWildcardOrigin() throws Exception
|
||||||
|
{
|
||||||
|
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
|
||||||
|
String origin = "http://subdomain.example.com";
|
||||||
|
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
|
||||||
|
tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
|
||||||
|
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
|
||||||
|
|
||||||
|
String request = "" +
|
||||||
|
"GET / HTTP/1.1\r\n" +
|
||||||
|
"Host: localhost\r\n" +
|
||||||
|
"Origin: " + origin + "\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_CREDENTIALS_HEADER));
|
||||||
|
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleRequestWithMatchingWildcardOriginAndMultipleSubdomains() throws Exception
|
||||||
|
{
|
||||||
|
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
|
||||||
|
String origin = "http://subdomain.subdomain.example.com";
|
||||||
|
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
|
||||||
|
tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
|
||||||
|
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
|
||||||
|
|
||||||
|
String request = "" +
|
||||||
|
"GET / HTTP/1.1\r\n" +
|
||||||
|
"Host: localhost\r\n" +
|
||||||
|
"Origin: " + origin + "\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_CREDENTIALS_HEADER));
|
||||||
|
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleRequestWithMatchingOrigin() throws Exception
|
public void testSimpleRequestWithMatchingOrigin() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -327,6 +373,7 @@ public class CrossOriginFilterTest
|
||||||
|
|
||||||
public static class ResourceServlet extends HttpServlet
|
public static class ResourceServlet extends HttpServlet
|
||||||
{
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
private final CountDownLatch latch;
|
private final CountDownLatch latch;
|
||||||
|
|
||||||
public ResourceServlet(CountDownLatch latch)
|
public ResourceServlet(CountDownLatch latch)
|
||||||
|
|
Loading…
Reference in New Issue