如果 @PathVariable 包含点(.),会被截断

1、概览

使用 Spring 的 @PathVariable@RequestMapping 来映射包含点的请求时,最后一个 URI 路径变量的值被会截断。

2、原因

具体来说,Spring 认为最后一个点后面的任何内容都是文件扩展名,如 .json.xml,因此,它会截断值以检索路径变量。

来看一个使用路径变量的例子:

@RestController
public class CustomController {
    @GetMapping("/example/{firstValue}/{secondValue}")
    public void example(@PathVariable("firstValue") String firstValue,
      @PathVariable("secondValue") String secondValue) {
        // ...  
    }
}

如上,考虑以下请求 URL 以及 firstValuesecondValue 变量的值:

  • example/gallery/linkfirstValue = "gallery"secondValue = "link"
  • example/gallery.df/link.ar URLfirstValue = "gallery.df "secondValue = "link"
  • example/gallery.df/link.com.arfirstValue = "gallery.df"secondValue = "link.com"

可以看到,第一个变量不受影响,但第二个带点(.)的变量总是被截断。

3、解决办法

解决这种不便的方法之一是修改 @PathVariable 定义,添加一个 regex(正则)映射。这样,任何点(包括最后一个点)都将被视为参数的一部分:

@GetMapping("/example/{firstValue}/{secondValue:.+}")   
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

避免这一问题的另一种方法是在 @PathVariable 末尾添加斜线。包围第二个变量,使其不受 Spring 默认行为的影响:

@GetMapping("/example/{firstValue}/{secondValue}/")

上述两种解决方案适用于单个请求映射。

如果想在全局 MVC 层面更改行为,就需要提供自定义配置。为此,可以实现配置类 WebMvcConfigurer 并覆写其 configurePathMatch(PathMatchConfigurer configurer) 方法来调整 PathMatchConfigurer

package cn.springdoc.demo.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 在匹配请求模式时是否使用后缀模式匹配(".*")。
        configurer.setUseSuffixPatternMatch(false);
    }
}

注意,这种方法会影响所有 URL。

3.1、弃用警告

自 Spring 5.2.4 起,setUseSuffixPatternMatch(boolean) 方法已被弃用,以阻止在请求路由和内容协商中使用路径扩展(后缀)。从根本上说,当前的实现很难保护 Web 应用免受 反射式文件下载(RFD) 攻击。

此外,自 Spring Framework 5.3 起,后缀模式匹配将仅适用于明确注册的后缀,以防止任意扩展(后缀)。

总之,从 Spring 5.3 开始,不需要使用 setUseSuffixPatternMatch(false),因为它默认已被禁用。

4、总结

本文介绍了如何解决在 Spring MVC 中使用 @PathVariable 处理带点(.) 的 URI 路径参数时,参数值被截断的问题。


Ref:https://www.baeldung.com/spring-mvc-pathvariable-dot