46

这不是重复引用的问题,因为它是 Spring 特定的。谁添加了这个(事实发生后 3 年!)并没有费心阅读问题或评论线程来查看真正的答案是什么。接受的答案并不完全是答案,但答案的作者从未像我要求的那样回来编辑它。

鉴于下面的 restful 方法,Spring 3.1 给出了 400 错误“客户端发送的请求在语法上不正确 ()”。当token参数包含 URL 编码的斜杠 (%2F) 时,例如“ https://somewhere.com/ws/stuff/lookup/resourceId/287559/token/R4o6lI%2FbBx43/userName/jim ” 没有 %2F 一切正常美好的。第 3 方已经在调用此服务(当然!)所以我无法更改他们发送的内容,至少在短期内是这样。关于如何在服务器端解决这个问题的任何想法?

这个问题在这里得到了很好的描述https://jira.springsource.org/browse/SPR-8662虽然这个问题与我没有使用的 UriTemplate 有关,我可以说。

@RequestMapping("/ws/stuff/**")
@Controller
public class StuffController {
  @RequestMapping(value = "/ws/stuff/lookup/resourceId/{resourceId}/token/{token}/userName/{userName}", method = RequestMethod.GET)
   public @ResponseBody
   String provisionResource(@PathVariable("resourceId") String resourceId, @PathVariable("token") String token, @PathVariable("userName") String userName, ModelMap modelMap,
         HttpServletRequest request, HttpServletResponse response) {
      return handle(resourceId, userName, request, token, modelMap);
   }
}

注意:这是在 Glassfish 3.1.2 上,起初是 Grizzly/Glassfish 不接受斜线,但是

-Dcom.sun.grizzly.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

解决了这个问题。

asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-2.http.encoded-slash-enabled=true

似乎没有帮助。

4

10 回答 10

24

对于spring-boot,以下是诀窍

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

}
于 2016-06-02T20:03:20.803 回答
14

这可能是您的答案:urlencoded 正斜杠正在破坏 URL

我建议不要将其放在路径中,而是将其移至请求参数。

解决方法:

您可以将 RequestMapping 更改为

@RequestMapping(value = "/ws/stuff/lookup/resourceId/**", method = RequestMethod.GET) 

然后从请求对象中手动解析路径变量。

于 2012-11-21T07:33:38.187 回答
10

Spring Boot 2+ / Spring(安全)5+ / Java 8+ 的 2019 年更新:

由于我对iamiddy 答案的编辑被拒绝,我还想提供 Spring Boot 2 + 的完整解决方案作为单独的答案。

Spring5 WebMvcConfigurerAdapter/ Java8 已弃用,可以直接替换为 InterfaceWebMvcConfigurer结尾:

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

另外,您还需要配置 Spring(Strict)HttpFirewall以避免错误消息阻塞编码斜线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 将在可用时使用上述HttpFirewallBean - 否则可能需要WebSecurity按照此处所述进行配置:

于 2019-10-09T12:06:50.483 回答
7

这是 Spring 3.2.4 的修复(也应该适用于其他版本)。必须覆盖默认的 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());
        }
    }

并将其注入映射处理程序:

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

经过一天的努力,它现在对我有用:-)

建议 Spring 团队使用https://jira.springsource.org/browse/SPR-11101

于 2013-11-20T11:07:17.130 回答
7

对于弹簧启动应用程序,这对我有用..

版本 1 添加

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

到您的application.properties文件

版本 2 像这样运行您的 Spring Boot 应用程序。

static void main(String[] args) {
    System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
    SpringApplication.run this, args
}

版本 3 或使用 -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 运行您的 java 应用程序

这个为我修复了 %2F 编码的斜杠路径变量。

于 2016-02-25T19:12:40.423 回答
6

我找到了这个对我有用的解决方案;

System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");

就在 springApplication.run(args); 之前

并在 Application 类中添加以下代码

 @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
于 2016-06-07T10:27:23.783 回答
1

为了避免手动解析变量,我做了以下操作:

  1. 在执行任何其他代码之前添加以下内容:
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
  1. 在控制器中,添加 2 个变量而不是 1 个,例如:
    @RequestMapping(value = "/api/devices-by-name/device={deviceId}/restconf/data/ietf-interfaces:interfaces-state/interface={dpuIdPrefix}/{dpuIdSuffix}",
            method = RequestMethod.GET,
            produces = "application/json")
    public ResponseEntity<String> getInterfaceState(@PathVariable(value = "deviceId") String deviceId,
                                                    @PathVariable(value = "dpuIdPrefix") String dpuIdPrefix,
                                                    @PathVariable(value = "dpuIdSuffix") String dpuIdSuffix) {
        String dpuId = dpuIdPrefix + "/" + dpuIdSuffix;

有了它,我可以检索以下内容:

curl -s -X GET http://localhost:9090/api/devices-by-name/device=ZNSDX16DPU03/restconf/data/ietf-interfaces:interfaces-state/interface=gfast%200%2F14

如果斜杠是可选的,那么您可能需要配置两个不同的请求映射。

于 2021-05-20T15:44:18.760 回答
0

我们刚刚在我的办公室遇到了这个问题,我们根据Solubris 所说的将它放在查询参数中的位置做了上面的建议。唯一的额外要求是数据也可以有一个“&”,这会弄乱查询参数。我们所要做的就是在将文本发送到 URL 之前对其进行编码,甚至“&”也被过滤掉了。

于 2014-04-10T19:57:59.040 回答
0

另一个答案是编码"/"两次,这将产生"%252F".
在您映射的端点中,Spring 会将其解码回"%2F". 您只需要使用以下内容再次对其进行解码:

URLDecoder.decode(encoded_URL, "UTF-8");

于 2019-05-23T08:24:00.083 回答
0

以下解决了 BACK_SLASH 问题:

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

但是,可以通过 application.yml 完成相同的功能。

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true

此设置不起作用。我没有找到方法,并且仍在寻找它。

于 2020-07-22T08:31:25.723 回答