提交 2f6d86b7 编写于 作者: B Brian Clozel

Fix OutOfBoundsExceptio in ResourceUrlEncodingFilter

Prior to this change, the `ResourceUrlEncodingFilter` would try to
lookup resources URLs as soon as the given URL would be longer than the
expected context+servlet prefix path. This can lead to
OutOfBoundsExceptions when the provided URL does not start with that
prefix and still has the required length.

This commit makes sure that all candidate URLs for resources lookup are
prefixed with the cached servlet and context path. This underlines the
fact that the `ResourceUrlEncodingFilter` does not support relative URLs
for now and delegates to the native servlet implementation in that case.

Issue: SPR-13861
上级 952a3170
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
......@@ -37,6 +37,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
* @author Jeremy Grelle
* @author Rossen Stoyanchev
* @author Sam Brannen
* @author Brian Clozel
* @since 4.1
*/
public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
......@@ -56,9 +57,11 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
private final HttpServletRequest request;
/* Cache the index of the path within the DispatcherServlet mapping */
/* Cache the index and prefix of the path within the DispatcherServlet mapping */
private Integer indexLookupPath;
private String prefixLookupPath;
public ResourceUrlEncodingResponseWrapper(HttpServletRequest request, HttpServletResponse wrapped) {
super(wrapped);
this.request = request;
......@@ -72,15 +75,14 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
return super.encodeURL(url);
}
initIndexLookupPath(resourceUrlProvider);
if (url.length() >= this.indexLookupPath) {
String prefix = url.substring(0, this.indexLookupPath);
initLookupPath(resourceUrlProvider);
if (url.startsWith(this.prefixLookupPath)) {
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 + suffix);
return super.encodeURL(this.prefixLookupPath + lookupPath + suffix);
}
}
......@@ -92,16 +94,18 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter {
ResourceUrlProviderExposingInterceptor.RESOURCE_URL_PROVIDER_ATTR);
}
private void initIndexLookupPath(ResourceUrlProvider urlProvider) {
private void initLookupPath(ResourceUrlProvider urlProvider) {
if (this.indexLookupPath == null) {
String requestUri = urlProvider.getPathHelper().getRequestUri(this.request);
String lookupPath = urlProvider.getPathHelper().getLookupPathForRequest(this.request);
this.indexLookupPath = requestUri.lastIndexOf(lookupPath);
this.prefixLookupPath = requestUri.substring(0, this.indexLookupPath);
if ("/".equals(lookupPath) && !"/".equals(requestUri)) {
String contextPath = urlProvider.getPathHelper().getContextPath(this.request);
if (requestUri.equals(contextPath)) {
this.indexLookupPath = requestUri.length();
this.prefixLookupPath = requestUri;
}
}
}
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
......@@ -150,6 +150,25 @@ public class ResourceUrlEncodingFilterTests {
});
}
// SPR-13847
@Test
public void encodeUrlPreventStringOutOfBounds() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/context-path/index");
request.setContextPath("/context-path");
request.setServletPath("");
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("index?key=value");
assertEquals("index?key=value", result);
}
});
}
protected ResourceUrlProvider createResourceUrlProvider(List<ResourceResolver> resolvers) {
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
handler.setLocations(Arrays.asList(new ClassPathResource("test/", getClass())));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册