Springboot doesn't let through percentage and backslash in URL

我的梦境 提交于 2021-02-07 20:37:24

问题


We got a get request that sends string characters in url, so we use path variables to receive them. Apparently there is no way that the calling service would change its method of calling backend so we need to be able to accept a url with the following unencoded characters:

When percentage sign % is sent a http 400 is returned. It does go through if the two characters following % make up an UTF-encoded character

Backslash is converted into a forward slash. I need it to stay backslash.

I'm guessing these might be Tomcat or servlet configuration issues.

(spring boot version 1.5.14.RELEASE)


回答1:


Percent signs (%) should be no problem if you properly URL encode them (%25). However, slashes and backslashes will not work with Tomcat, even if you encode them (%2F and %5C).

You could set the following properties when running the application:

-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true

However, this won't fix the issue, because in this case, those encoded slashes will be recognized as real ones. So, let's say you have the following controller:

@ResponseBody
@RequestMapping("/api/{foo}")
public String getFoo(@PathVariable String foo) {
    return foo;
}

Well, then if you call /api/test%5Ctest, it won't be able to find the correct path. A solution to this problem is to use wildcard matchers and to parse the URL itself from the incoming HttpServletRequest:

@RequestMapping("/api/**")
public String getFoo(HttpServletRequest request) {
    // ...
}

Another solution is to use a completely different web container. For example, when using Jetty, this isn't a problem at all, and URL encoded slashes and backslashes will both work.




回答2:


Spring 5 now blocks encoded percent signs by default. To enable them, create a new Bean that calls setAllowUrlEncodedPercent()

@Bean
public HttpFirewall allowEncodedParamsFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedPercent(true);    
    return firewall;
}

There are similar method-calls for forward- and backwards-slash




回答3:


What you are experiencing is not specific to Spring Boot. Instead, it's a restriction of HTTP.

The HTTP standard requires that any URL containing the percent characters must be decoded by the web server (cf page 36):

If the Request-URI is encoded using the "% HEX HEX" encoding [42], the origin server MUST decode the Request-URI in order to properly interpret the request.

As a result, it's not possible to escape the slash character reliably.

Therefore, when the slash is used in a URL – with or without encoding – it will be treated as a path separator. So it cannot be used in a Spring Boot path variable. Similar problem exist for the percent sign and backslash.

Your best options are to use query parameters or a POST request.

In the following URL, the value test_with_/and_% is transmitted:

https://host/abc/def?text=test_with_%2F_and%25



回答4:


final String path =
                    request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();
            final String bestMatchingPattern =
                    request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();

            String arguments = new AntPathMatcher().extractPathWithinPattern(bestMatchingPattern, path);



            if (null != arguments && !arguments.isEmpty()) {
                pattern = pattern + '/' + arguments;
            }

I also faced similar problem and I have used this so hope this might help



来源:https://stackoverflow.com/questions/51108291/springboot-doesnt-let-through-percentage-and-backslash-in-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!