Encoded slash (/) with Spring RequestMapping path param gives HTTP 400

前端 未结 9 772
陌清茗
陌清茗 2020-12-05 00:10

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

相关标签:
9条回答
  • 2020-12-05 00:28

    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

    0 讨论(0)
  • 2020-12-05 00:29

    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);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-05 00:30

    2019 Update for Spring Boot 2+ / Spring (Security) 5+ / Java 8+:

    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:

    0 讨论(0)
  • 2020-12-05 00:32

    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.

    0 讨论(0)
  • 2020-12-05 00:43

    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);
        }
    
    0 讨论(0)
  • 2020-12-05 00:45

    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");

    0 讨论(0)
提交回复
热议问题