Spring Boot 2 和 Kotlin 的“URL 未标准化”

Posted

技术标签:

【中文标题】Spring Boot 2 和 Kotlin 的“URL 未标准化”【英文标题】:"URL was not normalized" with Spring Boot 2 and Kotlin 【发布时间】:2019-03-08 11:38:40 【问题描述】:

在我当前的项目中,我们在OpenshiftKubernetes 中部署了几个Spring Boot 1.5.4.RELEASE 微服务。我们已经配置了一个 Apache Proxy Balancer:

From                            To
/msa/microname1          ->     /
/msa/microname2          ->     /
...

最近我们介绍了Spring Boot 2,并使用Kotlin 开发了一个新的微服务。考虑到/health/info 之类的url 放在/actuator 路径下,我们以相同的方式配置平衡器。 现在,当我们使用这个新微服务的任何端点(/health 或我们的任何端点)时,我们都会遇到如下错误:

org.springframework.security.web.firewall.RequestRejectedException: 由于 URL 未规范化,请求被拒绝...

我们在微服务中截取的路径开头多了一个斜线://<path_to_resource>

当我使用微服务 url 时,我可以毫无问题地获得资源,但是当使用代理平衡器映射时,我们遇到了上述问题。

我们检查了我们的代理平衡器,它的配置方式与其他平衡器相同。 我们必须考虑Spring Boot 2 上的任何额外配置吗? 这可能是与Kotlin 相关的问题吗?

更新

作为一项调整,我们已将 DefaultHttpFirewall 配置为允许 url 加斜杠,但这并不能解决双斜杠的问题。它只是掩盖了问题。

@Bean
fun allowUrlEncodedSlash(): HttpFirewall 
    var firewall: DefaultHttpFirewall = DefaultHttpFirewall()
    firewall.setAllowUrlEncodedSlash(true)
    return firewall


override fun configure(web: WebSecurity) 
    web.httpFirewall(allowUrlEncodedSlash())

【问题讨论】:

【参考方案1】:

检查这个答案:https://***.com/a/48644226/10451721

这似乎与您的问题相同,但使用的是 Java 而不是 Kotlin。

默认情况下,Spring 不喜欢 URL 中的 //

我已经为您转换了链接答案中的 Java:

@Bean
fun allowUrlEncodedSlashHttpFirewall(): HttpFirewall 
    val firewall = StrictHttpFirewall()
    firewall.setAllowUrlEncodedSlash(true)
    return firewall

【讨论】:

是的,我们昨天做了同样的事情,但是我们不方便修改 HttpFirewall。我们仍在寻找根本原因,因为我们没有添加任何额外的栏。至少我是这么认为的。【参考方案2】:

通过在我们的平衡器中向应用程序添加上下文来解决。 现在我们所有的端点在我们的微服务中都有一个上下文,在 application.yml 中定义。

From                            To
/msa/microname1          ->     /
/msa/microname2          ->     /
/msa/Kotlinname/kt       ->     /kt

【讨论】:

以上是关于Spring Boot 2 和 Kotlin 的“URL 未标准化”的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2 和 Kotlin 的“URL 未标准化”

如何启动 2.4.0 和 kotlin 1.4.20

使用 Spring Boot 2 和 Kotlin 进行 Jackson 反序列化,无法构造 `java.time.LocalDate` 的实例

带有 Spring Boot 2.0 @ConfigurationProperties 的 Kotlin 无法正常工作

如何模拟测试 Kotlin Spring Boot 2 应用程序

Kotlin Spring Boot 中的控制器验证