Spring 5.0.3 RequestRejectedException:由于网址未规范化,因此请求被拒绝


问题内容

不知道这是Spring 5.0.3的错误还是新功能可以修复我的问题。

升级后,出现此错误。有趣的是,此错误仅在我的本地计算机上。使用HTTPS协议的测试环境中的相同代码可以正常工作。

继续…

我收到此错误的原因是因为我用于加载结果JSP页面的URL是/location/thisPage.jsp。评估代码request.getRequestURI()会给我结果/WEB-INF/somelocation//location/thisPage.jsp。如果我将JSP页面的URL修复为此location/thisPage.jsp,则一切正常。

所以我的问题是,我应该/从JSP代码的路径中删除吗,因为这是今后的要求。或者Spring引入了一个错误,因为我的机器和测试环境之间的唯一区别是协议HTTP与HTTPS。

 org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL was not normalized.
    at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:123)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)

问题答案:

Spring Security Documentation提到了阻塞请求的原因。

例如,它可能包含路径遍历序列(例如/../)或多个正斜杠(//),这也可能导致模式匹配失败。一些容器在执行servlet映射之前将它们标准化,但其他容器则没有。为了避免此类问题,FilterChainProxy使用HttpFirewall策略检查并包装请求。默认情况下,未规范化的请求将自动被拒绝,并且出于匹配目的,将删除路径参数和重复的斜杠。

因此,有两种可能的解决方案-

  1. 删除双斜杠(首选方法)
  2. 通过使用以下代码来自定义StrictHttpFirewall,在Spring Security中允许//。
    步骤1 创建自定义防火墙,以允许在URL中使用斜杠。
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedSlash(true);    
    return firewall;
}

步骤2,然后在Websecurity中配置此bean

@Override
public void configure(WebSecurity web) throws Exception {
    //@formatter:off
    super.configure(web);
    web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
....
}

步骤2是可选步骤,Spring Boot仅需要声明一个类型为bean的bean HttpFirewall