This is not a duplicate referenced question, because it is Spring specific. Whoever added that (3 years after the fact!) didn\'t bother to read the question or comment
Here is a fix for Spring 3.2.4 (should work for other versions as well). One must overwrite the default UrlPathHelper
public class UrlPathHelperFixed extends UrlPathHelper {
public UrlPathHelperFixed() {
super.setUrlDecode(false);
}
@Override
public void setUrlDecode(boolean urlDecode) {
if (urlDecode) {
throw new IllegalArgumentException("Handler [" + UrlPathHelperFixed.class.getName() + "] does not support URL decoding.");
}
}
@Override
public String getServletPath(HttpServletRequest request) {
return getOriginatingServletPath(request);
}
@Override
public String getOriginatingServletPath(HttpServletRequest request) {
return request.getRequestURI().substring(request.getContextPath().length());
}
}
And inject it to the Mapping Handler:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="order" value="-1"></property>
<property name="urlPathHelper">
<bean class="com.yoochoose.frontend.spring.UrlPathHelperFixed"/>
</property>
</bean>
After a day of hard works it works now for me :-)
It was suggested to Spring team as https://jira.springsource.org/browse/SPR-11101
for spring-boot, the following did the trick
@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
As my edit to iamiddy's answer was rejected I want to also provide the complete solution for Spring Boot 2 + as an separate answer.
The WebMvcConfigurerAdapter
is deprecated with Spring5 / Java8 and can be replaced directly with the Interface WebMvcConfigurer
ending up with:
@SpringBootApplication
public class Application extends WebMvcConfigurer {
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
Plus you also need to configure Spring's (Strict)HttpFirewall
to avoid the blocking of encoded slashes with the error message The request was rejected because the URL contained a potentially malicious String "%2F"
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowUrlEncodedSlash(true);
return firewall;
}
Spring Boot will use the above HttpFirewall
Bean when available - otherwise it might be necessary to configure the WebSecurity
as mentioned here:
The following resolved the BACK_SLASH issue:
public static void main(String[] args) throws Exception {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run(Application.class, args);
}
But, same functionality could be done via application.yml.
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true
This setting doesn't work. I did not find a way for that, and still looking at it.
I have found this solution which is working for me;
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
just before springApplication.run(args);
and add below code in Application class
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
Another answer would be to encode "/"
twice, which would produce "%252F"
.
In your mapped endpoint, Spring will decode it back to "%2F"
. All you need more is to decode it one more time using something like this:
URLDecoder.decode(encoded_URL, "UTF-8");