Sanitize request URL in ResourceUrlEncodingFilter
Prior to this change, ResourceUrlEncodingFilter and ResourceUrlProvider would try to resolve the resource path using the full request URL (i.e. request path and request parameters), whereas the request path is the only information to consider. This would lead to StringIndexOutOfBoundsExceptions when the path + request params information was given to the AntPathMatcher. This commit makes the appropriate change to both ResourceUrlEncodingFilter and ResourceUrlProvider, in order to only select the request path. Issue: SPR-13374
This commit is contained in:
parent
04cff89eb7
commit
0b9c3de320
|
@ -74,10 +74,12 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
|
|||
initIndexLookupPath(resourceUrlProvider);
|
||||
if (url.length() >= this.indexLookupPath) {
|
||||
String prefix = url.substring(0, this.indexLookupPath);
|
||||
String lookupPath = url.substring(this.indexLookupPath);
|
||||
int suffixIndex = getQueryParamsIndex(url);
|
||||
String suffix = url.substring(suffixIndex);
|
||||
String lookupPath = url.substring(this.indexLookupPath, suffixIndex);
|
||||
lookupPath = resourceUrlProvider.getForLookupPath(lookupPath);
|
||||
if (lookupPath != null) {
|
||||
return super.encodeURL(prefix + lookupPath);
|
||||
return super.encodeURL(prefix + lookupPath + suffix);
|
||||
}
|
||||
}
|
||||
return super.encodeURL(url);
|
||||
|
@ -95,6 +97,11 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
|
|||
this.indexLookupPath = requestUri.lastIndexOf(lookupPath);
|
||||
}
|
||||
}
|
||||
|
||||
private int getQueryParamsIndex(String url) {
|
||||
int index = url.indexOf("?");
|
||||
return index > 0 ? index : url.length();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -172,11 +172,13 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
|
|||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting resource URL for requestURL=" + requestUrl);
|
||||
}
|
||||
int index = getLookupPathIndex(request);
|
||||
String prefix = requestUrl.substring(0, index);
|
||||
String lookupPath = requestUrl.substring(index);
|
||||
int prefixIndex = getLookupPathIndex(request);
|
||||
int suffixIndex = getQueryParamsIndex(requestUrl);
|
||||
String prefix = requestUrl.substring(0, prefixIndex);
|
||||
String suffix = requestUrl.substring(suffixIndex);
|
||||
String lookupPath = requestUrl.substring(prefixIndex, suffixIndex);
|
||||
String resolvedLookupPath = getForLookupPath(lookupPath);
|
||||
return (resolvedLookupPath != null) ? prefix + resolvedLookupPath : null;
|
||||
return (resolvedLookupPath != null) ? prefix + resolvedLookupPath + suffix : null;
|
||||
}
|
||||
|
||||
private int getLookupPathIndex(HttpServletRequest request) {
|
||||
|
@ -185,6 +187,11 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
|
|||
return requestUri.indexOf(lookupPath);
|
||||
}
|
||||
|
||||
private int getQueryParamsIndex(String lookupPath) {
|
||||
int index = lookupPath.indexOf("?");
|
||||
return index > 0 ? index : lookupPath.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the given path against configured resource handler mappings and
|
||||
* if a match is found use the {@code ResourceResolver} chain of the matched
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -106,6 +106,23 @@ public class ResourceUrlEncodingFilterTests {
|
|||
});
|
||||
}
|
||||
|
||||
// SPR-13374
|
||||
@Test
|
||||
public void encodeURLWithRequestParams() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
request.setContextPath("/");
|
||||
request.setAttribute(ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.filter.doFilterInternal(request, response, new FilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
String result = ((HttpServletResponse)response).encodeURL("/resources/bar.css?foo=bar&url=http://example.org");
|
||||
assertEquals("/resources/bar-11e16cf79faee7ac698c805cf28248d2.css?foo=bar&url=http://example.org", result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected ResourceUrlProvider createResourceUrlProvider(List<ResourceResolver> resolvers) {
|
||||
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
|
||||
handler.setLocations(Arrays.asList(new ClassPathResource("test/", getClass())));
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
|
@ -74,6 +75,18 @@ public class ResourceUrlProviderTests {
|
|||
assertEquals("/resources/foo.css", url);
|
||||
}
|
||||
|
||||
// SPR-13374
|
||||
@Test
|
||||
public void getStaticResourceUrlRequestWithRequestParams() {
|
||||
initTranslator();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContextPath("/");
|
||||
request.setRequestURI("/");
|
||||
|
||||
String url = this.translator.getForRequestUrl(request, "/resources/foo.css?foo=bar&url=http://example.org");
|
||||
assertEquals("/resources/foo.css?foo=bar&url=http://example.org", url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFingerprintedResourceUrl() {
|
||||
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
|
||||
|
|
Loading…
Reference in New Issue