Spring Security 4.2 中的 StrictHttpFirewall 与 Spring MVC @MatrixVariable

Posted

技术标签:

【中文标题】Spring Security 4.2 中的 StrictHttpFirewall 与 Spring MVC @MatrixVariable【英文标题】:StrictHttpFirewall in spring security 4.2 vs spring MVC @MatrixVariable 【发布时间】:2018-07-12 19:56:26 【问题描述】:

升级到 spring security 4.2.4 后,我发现 StrictHttpFirewall 现在是默认设置。 不幸的是,它不能很好地与 spring MVC @MatrixVariable 一起使用,因为“;”不再被允许。 如何解决这个问题?

例子:

@GetMapping(path = "/param")
public void example(@PathVariable String param,
                    @MatrixVariable Map<String, String> matrix) 
    //...

这可以这样调用:

mockMvc.perform(get("/someparam;key=value"))

矩阵图将被填充。 现在 spring security 阻止了它。

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"

at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:140)

我可以使用允许分号的自定义 HttpFirewall。 有没有办法在不使用禁止字符的情况下使用@MatrixVariable?

顺便说一句:javadoc 不正确https://docs.spring.io/autorepo/docs/spring-security/4.2.x/apidocs/index.html?org/springframework/security/web/firewall/StrictHttpFirewall.html

自:

5.0.1

我猜它是向后移植的?

【问题讨论】:

这里是如何允许分号: 【参考方案1】:

您可以使用自定义的 StrictHttpFirewall 实例稀释默认的 spring 安全防火墙(风险自负)

@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() 
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedSlash(true);
    firewall.setAllowSemicolon(true);
    return firewall;

然后在WebSecurity中使用这个自定义的防火墙bean(Spring boot不需要这个改动)

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

这适用于 Spring Security 4.2.4+,但当然会带来一些风险!

【讨论】:

StrictHttpFirewall 阻止请求,因为允许它们是危险的。由于 Servlet 规范中的模糊性以及 Servlet 容器之间的不一致行为(没有拒绝 URL 编码的分号),我们无法找到防止此类攻击的好方法。 那么 Spring MVC @MatrixVariable 也必须更改。 由于某种原因,它不适用于 Spring Security 5.0.3.RELEASE。 不需要在configure(WebSecurity web) 方法中连接bean,因为WebSecurity 实例尝试使用ApplicationContextAware 注释在上下文中查找HttpFirewall 类型的bean。换句话说,仅仅实例化一个 HttpFirewall 类型的 bean 就足够了。 有什么风险?有人可以解释一下为什么这是必要的吗?【参考方案2】:

正如Крис 在评论中提到的,如果您更喜欢使用 XML 方法,您可以将以下部分添加到您的 securityContext.xml(或任何与 spring-security 相关的 xml-config 调用):

<bean id="allowSemicolonHttpFirewall" 
      class="org.springframework.security.web.firewall.StrictHttpFirewall"> 
        <property name="allowSemicolon" value="true"/> 
</bean> 
<security:http-firewall ref="allowSemicolonHttpFirewall"/>

&lt;bean&gt; 部分定义了一个新的 StrictHttpFirewall bean,其 id 为 allowSemicolonHttpFirewall,然后通过引用该 id 在 &lt;security&gt; 标记中将其设置为默认 http-firewall。

【讨论】:

【参考方案3】:

我使用了以下两个的组合

    https://***.com/a/48636757/6780127 https://***.com/a/30539991/6780127

第一个解决了 The request was rejected because the URL contained a potentially malicious String ";" 第二个解决了 Spring MVC Missing matrix variable

当我将 Spring Security 与 Spring Web 一起使用时,我必须同时做这两个问题,现在问题已解决。

我发现使用@MatrixVariable 跟随模式很有用。首先在 Url 中必须提到 num 才能将其用作 @MatrixVariable

@RequestMapping(method = RequestMethod.GET,value = "/testnum")
@ResponseBody
public ResponseEntity<String> getDetail(@MatrixVariable String num)
    return new ResponseEntity<>("test"+num, HttpStatus.OK);

【讨论】:

以上是关于Spring Security 4.2 中的 StrictHttpFirewall 与 Spring MVC @MatrixVariable的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 4.2 不工作

Spring Security入门

Spring Security---详解登录步骤

Spring Security-用户密码自定义加密

将过期时间添加到 Spring Security 记住我的 cookie

grails spring security rest status 401重定向到控制器的动作以抛出自定义错误消息