为什么括号之类的某些字符会在 Spring REST 端点中导致 400 BAD REQUEST 错误?

Why do some characters like brackets cause a 400 BAD REQUEST error in a Spring REST endpoint?

我正在尝试调用 Spring 应用程序中通过 GET 方法公开的 REST API。发送请求时,我注意到控制器不支持某些字符,并且在控制器代码执行之前立即 returns 400 BAD_REQUEST 错误。

重现错误的字符:

[]{}|\

像下面这样的所有其他字符都不会重现错误:

&+<>$?!@°*~#"'/

工作请求示例:

http://localhost:8888/api?a=&b=Hello&c=&d=&e=0&f=1

非工作请求示例:

http://localhost:8888/api?a=&b=%5BHello&c=&d=&e=0&f=1

字符在字符串中的位置对此错误没有任何影响。 当上述六个字符之一出现在任何字符串参数中时,就会出现此错误。

控制器代码如下:

@GetMapping
public ResponseEntity<Object> getEmails(
        @RequestParam(required = false, name = "a") String a,
        @RequestParam(required = false, name = "b") String b,
        @RequestParam(required = false, name = "c") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime c,
        @RequestParam(required = false, name = "d") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime d,
        @RequestParam(name = "e") Integer e,
        @RequestParam(name = "f") Integer f
) {
    return new ResponseEntity<>(myService.doSomeStuff(a, b, c, d, e, f), HttpStatus.OK);
}

我们使用 Spring 以及以下 Jackson 依赖项:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.3</version>
    </dependency>

您需要在客户端对 URL 进行编码。

http://localhost:8083?a=asd[

你应该得到这个

http://localhost:8083?a=asd%5B

客户端通常会提供URL编码的函数,请查看其文档。如果您使用像 Postman 这样的客户端进行测试,那么您可以右键单击地址栏,然后您可以选择对 URL.

进行编码

[ 这样的一些字符被认为是允许的但不安全的字符,这就是需要编码的原因。

稍后编辑:

我已经测试了您的代码和请求,一切正常。我所做的唯一更改是在控制器方法中 return 字符串而不是响应实体。

@RestController
class Ctrl {
    @GetMapping
    public String getEmails(
            @RequestParam(required = false, name = "a") String a,
            @RequestParam(required = false, name = "b") String b,
            @RequestParam(required = false, name = "c") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime c,
            @RequestParam(required = false, name = "d") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime d,
            @RequestParam(name = "e") Integer e,
            @RequestParam(name = "f") Integer f
    ) {
        return "";
    }
}

curl --location --request GET 'http://localhost:8083?a=&b=%5BHello&c=&d=&e=0&f=1'

您可以启用 spring debug/trace 日志记录并查看发生了什么。