带有 Spring RequestMapping 路径参数的编码斜杠 (%2F) 给出 HTTP 400
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13482020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encoded slash (%2F) with Spring RequestMapping path param gives HTTP 400
提问by Jim
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 thread to see what the real answer was. The accepted answer isn't quite the answer, but the author of the answer never came back and edited it like I asked.
这不是重复引用的问题,因为它是特定于 Spring 的。谁添加了(事实发生 3 年后!)并没有费心阅读问题或评论线程以查看真正的答案是什么。接受的答案并不完全是答案,但答案的作者从未像我问的那样回来编辑它。
Given the restful method below, Spring 3.1 gives a 400 error with "The request sent by the client was syntactically incorrect ()." when the tokenparameter contains a URL encoded slash (%2F), for example "https://somewhere.com/ws/stuff/lookup/resourceId/287559/token/R4o6lI%2FbBx43/userName/jim" Without the %2F everything works fine. A 3rd party is already calling this service (of course!) so I can't change what they send, in the short term at least. Any ideas on how to work around this on the server side?
鉴于下面的restful方法,Spring 3.1给出了一个400错误,“客户端发送的请求在语法上不正确()”。当token参数包含 URL 编码的斜杠 (%2F) 时,例如“ https://somewhere.com/ws/stuff/lookup/resourceId/287559/token/R4o6lI%2FbBx43/userName/jim”没有 %2F 一切正常美好的。第 3 方已经在调用此服务(当然!)所以我无法更改他们发送的内容,至少在短期内是这样。关于如何在服务器端解决这个问题的任何想法?
This problem is described very well here https://jira.springsource.org/browse/SPR-8662though that issue is related to UriTemplate which I am not using that I can tell.
这个问题在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);
}
}
Note: This is on Glassfish 3.1.2, and at first it was Grizzly/Glassfish not accepting the slash, but
注意:这是在 Glassfish 3.1.2 上,起初是 Grizzly/Glassfish 不接受斜线,但是
-Dcom.sun.grizzly.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
-Dcom.sun.grizzly.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
fixed that.
修好了。
asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-2.http.encoded-slash-enabled=true
asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-2.http.encoded-slash-enabled=true
didn't seem to help.
似乎没有帮助。
采纳答案by Solubris
This could be your answer: urlencoded Forward slash is breaking URL
这可能是您的答案:urlencoded 正斜杠正在破坏 URL
I would suggest not putting that in the path, move it to a request param instead.
我建议不要把它放在路径中,而是将它移到请求参数中。
Work around:
解决:
You could change the RequestMapping to
您可以将 RequestMapping 更改为
@RequestMapping(value = "/ws/stuff/lookup/resourceId/**", method = RequestMethod.GET)
and then parse the path variables manually from the request object.
然后从请求对象手动解析路径变量。
回答by iamiddy
for spring-boot, the following did the trick
对于 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);
}
}
回答by 30thh
Here is a fix for Spring 3.2.4 (should work for other versions as well). One must overwrite the default UrlPathHelper
这是 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());
}
}
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
向 Spring 团队建议https://jira.springsource.org/browse/SPR-11101
回答by manukyanv07
For spring boot application this worked for me..
对于 Spring Boot 应用程序,这对我有用..
Version 1Add
版本 1添加
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
to your application.propertiesfile
到您的application.properties文件
Version 2run your spring boot application like this.
版本 2像这样运行您的 Spring Boot 应用程序。
static void main(String[] args) {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
SpringApplication.run this, args
}
Version 3 or run your java application with -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
版本 3 或使用 -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 运行您的 java 应用程序
This fixed %2F encoded slash path variable for me.
这个固定的 %2F 编码斜杠路径变量适合我。
回答by Ankur Gupta
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);
就在 springApplication.run(args) 之前;
and add below code in Application class
并在 Application 类中添加以下代码
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
回答by mineralf
2019 Update for Spring Boot 2+ / Spring (Security) 5+ / Java 8+:
2019 年 Spring Boot 2+/Spring(安全)5+/Java 8+ 更新:
As my edit to iamiddy's answerwas rejected I want to also provide the complete solution for Spring Boot 2 + as an separate answer.
由于我对iamiddy 答案的编辑被拒绝,我还想提供 Spring Boot 2 + 的完整解决方案作为单独的答案。
The WebMvcConfigurerAdapteris deprecated with Spring5 / Java8 and can be replaced directly with the Interface WebMvcConfigurerending up with:
该WebMvcConfigurerAdapter已被弃用与Spring5 / Java8并且可以与接口直接替换WebMvcConfigurer结束了:
@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)HttpFirewallto avoid the blocking of encoded slashes with the error message The request was rejected because the URL contained a potentially malicious String "%2F"
另外,您还需要配置 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 will use the above HttpFirewallBean when available - otherwise it might be necessary to configure the WebSecurityas mentioned here:
Spring Boot 将HttpFirewall在可用时使用上述Bean - 否则可能需要WebSecurity按照此处所述进行配置:
回答by M. Sokólski
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:
另一个答案是编码"/"两次,这将产生"%252F".
在您映射的端点中,Spring 会将其解码回"%2F". 您所需要的只是使用以下内容再解码一次:
URLDecoder.decode(encoded_URL, "UTF-8");
URLDecoder.decode(encoded_URL, "UTF-8");
回答by rsteier
We just ran into this issue at my office, we did what was suggestion above from what Solubris saidwhere you put it in a query param. The only additional requirement is that the data could have an '&' as well, which would mess up the query param. All we had to do is encode the text before it is sent in the URL and even '&' were filtered out.
我们刚刚在我的办公室遇到了这个问题,我们根据Solubris 所说的将它放在查询参数中的位置做了上面的建议。唯一的额外要求是数据也可以有一个“&”,这会弄乱查询参数。我们所要做的就是在将文本发送到 URL 之前对文本进行编码,甚至“&”也被过滤掉了。

