Spring Boot 不允许 URL 中的百分比和反斜杠

Springboot doesn't let through percentage and backslash in URL

我们收到一个发送字符串字符的get请求url,所以我们使用路径变量来接收它们。显然,调用服务无法更改其调用后端的方法,因此我们需要能够接受具有以下未编码字符的 url:

发送百分号 % 时返回 http 400。如果 % 后面的两个字符组成一个 UTF 编码字符

,它确实会通过

反斜杠转换为正斜杠。我需要它来保留反斜杠。

我猜这些可能是 Tomcat 或 servlet 配置问题。

(spring 引导版本 1.5.14.RELEASE)

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;
            }

我也遇到过类似的问题,我用过这个,希望这能对你有所帮助

百分号 (%) 如果您正确 URL 对其进行编码 (%25),应该没有问题。但是,斜杠和反斜杠不适用于 Tomcat,即使您对它们进行编码(%2F%5C)也是如此。

您可以在 运行 应用程序时设置以下属性:

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

但是,这并不能解决问题,因为在这种情况下,那些经过编码的斜杠将被识别为真实斜杠。因此,假设您有以下控制器:

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

好吧,那么如果你调用/api/test%5Ctest,它将无法找到正确的路径。此问题的解决方案是使用通配符匹配器并从传入的 HttpServletRequest:

中解析 URL 本身
@RequestMapping("/api/**")
public String getFoo(HttpServletRequest request) {
    // ...
}

另一种解决方案是使用完全不同的网络容器。例如,使用 Jetty 时,这根本不是问题,URL 编码的斜杠和反斜杠都可以。

您遇到的问题并非 Spring Boot 所特有。相反,它是 HTTP 的限制。

HTTP 标准要求任何包含百分比字符的 URL 必须由 Web 服务器解码(参见第 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.

因此,无法可靠地转义斜线字符。

因此,当在 URL 中使用斜杠时——无论是否进行编码——它都将被视为路径分隔符。所以它不能用在 Spring 引导路径变量中。百分号和反斜杠存在类似问题。

您最好的选择是使用查询参数或 POST 请求。

在下面的URL中,传值test_with_/and_%

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

Spring 5 现在默认阻止编码百分号。要启用它们,请创建一个调用 setAllowUrlEncodedPercent()

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

forward- and backwards-slash

有类似的方法调用