【问题标题】:Springboot doesn't let through percentage and backslash in URLSpring Boot 不允许通过 URL 中的百分比和反斜杠
【发布时间】:2018-12-09 00:51:32
【问题描述】:

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

发送百分号 % 时,将返回 http 400。如果 % 后面的两个字符组成一个 UTF 编码字符,它确实会通过

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

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

(spring boot 版本 1.5.14.RELEASE)

【问题讨论】:

  • 最好发布一个正确的服务 URL 示例,您从浏览器中点击的具体内容以及导致此问题的原因。
  • medium.com/@as.vignesh/… 我知道这是一个老问题,但这解决了我的问题。

标签: rest spring-boot special-characters


【解决方案1】:

如果您正确地对它们进行 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) {
    // ...
}

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

【讨论】:

    【解决方案2】:

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

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

    forward- 和 backwards-slash 也有类似的方法调用

    【讨论】:

      【解决方案3】:

      您所遇到的并非特定于 Spring Boot。相反,这是对 HTTP 的限制。

      HTTP 标准要求任何包含百分号字符的 URL 都必须由 Web 服务器解码(参见第 36 页):

      如果使用“% HEX HEX”编码 [42] 对 Request-URI 进行编码,则 源服务器必须解码 Request-URI 才能正确 解释请求。

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

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

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-09
          • 2021-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-30
          • 1970-01-01
          • 2012-08-03
          相关资源
          最近更新 更多