带有Spring RequestMapping路径参数的编码斜杠(%2F)提供HTTP 400

时间:2012-11-20 20:58:56

标签: spring rest glassfish glassfish-3 spring-3

这不是重复的referenced question,因为它是特定于Spring的。无论谁添加了(事实发生3年后!)都没有费心去阅读问题或评论帖子,看看真正的答案是什么。接受的答案并不完全是答案,但答案的作者从未回过头来编辑它,就像我问的那样。

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

这个问题在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

似乎没有帮助。

9 个答案:

答案 0 :(得分:14)

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

}

答案 1 :(得分:11)

这可能是您的答案:urlencoded Forward slash is breaking URL

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

解决方法:

您可以将RequestMapping更改为

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

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

答案 2 :(得分: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) {
        String servletPath = getOriginatingServletPath(request);
        return servletPath;
    }

    @Override
    public String getOriginatingServletPath(HttpServletRequest request) {
        String servletPath = request.getRequestURI().substring(request.getContextPath().length());
        return servletPath;
    }
}

并将其注入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>

经过一天的艰苦努力,它现在适合我: - )

有人向Spring团队建议https://jira.springsource.org/browse/SPR-11101

答案 3 :(得分:5)

对于春季启动应用程序,这对我有用..

版本1 添加

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

到您的 application.properties 文件

版本2 像这样运行你的春季启动应用程序。

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

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

这个固定的%2F编码的斜杠路径变量对我来说。

答案 4 :(得分:5)

我找到了这个适合我的解决方案;

System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
就在此之前 springApplication.run(参数);

并在Application class

中添加以下代码
 @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

Spring Boot 2 + / Spring(Security)5 + / Java 8+的2019更新:

由于我对iamiddy's answer的编辑被拒绝了,所以我想同时提供Spring Boot 2 +的完整解决方案作为单独的答案。

{5}和Java8不推荐使用WebMvcConfigurerAdapter,可以直接将其替换为以以下内容结尾的接口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);
    }
}

另外,您还需要配置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将在可用时使用上述HttpFirewall Bean-否则可能需要像here所述配置WebSecurity

答案 8 :(得分: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

此设置无效。我没有找到解决这个问题的方法,并且还在寻找它。