Sping Boot & Spring WebFlux 3.1.5 -请求内容无效

xxe27gdn  于 12个月前  发布在  Spring
关注(0)|答案(1)|浏览(138)

我有一个Sping Boot 项目,它使用Spring WebFlux实现API。
我使用openapi-generator-maven-plugin插件来生成Swagger-to-Java对象。
当POST请求包含与Swagger API Spec不匹配的字段时,将返回以下响应

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "Invalid request content.",
    "instance": "/v1/internal/create"
}

字符串

问题是没有关于导致问题的字段和错误的具体信息。

我记得在较老的Sping Boot 版本中,有这样的信息。例如:字段ID应该是一个数字或类似的东西。
根据我到目前为止的发现,这是因为安全,不暴露于敏感的信息。
我还发现了两个可以用来解决这个问题的方法:
1.启用include-message属性(不推荐)

server:
  error:
    include-message: always

结果:虽然我添加了这个 prop ,但对我没有效果

1.在ControllerAdvice中从ResponseEntityExceptionHandler扩展handleMethodArgumentNotValid方法,如ResponseEntityExceptionHandler

结果:如果类来自Package org.springframework.web.servlet.mvc.method.annotation,则可以使用这种方法,但当我使用Spring WebFlux时,我的类来自Package org.springframework.web.reactive.result.method.annotation,其中不存在这种方法

所以任何关于如何解决它的建议将受到高度赞赏!

44u64gxh

44u64gxh1#

我发现应该做什么来返回正确的信息哪些字段没有通过验证
我使用扩展了ResponseEntityExceptionHandlerControllerAdvice,调试后发现这两个方法在模型验证期间被触发

  • WebExchangeBindException-如果有一些绑定问题。例如,我们有一个应该在100和200之间的数字,但用户设置为50
  • WebInputException-如果出现了一些格式化问题。例如,我们将字段定义为一个字符串,但用户发送的是一个字符串

示例实现:

@ControllerAdvice
@NonNullApi
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
    
    @Override
    protected Mono<ResponseEntity<Object>> handleWebExchangeBindException(WebExchangeBindException ex,
                                                                          HttpHeaders headers,
                                                                          HttpStatusCode status,
                                                                          ServerWebExchange exchange) {

        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, Objects.requireNonNull(ex.getBody().getDetail()));
        ex.getBindingResult().getFieldErrors()
                .forEach(fieldError ->  problemDetail.setProperty(fieldError.getField(),  fieldError.getDefaultMessage()));

        return Mono.just(ResponseEntity.status(HttpStatusCode.valueOf(400))
                .body(problemDetail));
    }

    @Override
    protected Mono<ResponseEntity<Object>> handleServerWebInputException(ServerWebInputException ex,
                                                                         HttpHeaders headers,
                                                                         HttpStatusCode status,
                                                                         ServerWebExchange exchange) {
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getCause().getMessage());
        return Mono.just(ResponseEntity.status(HttpStatusCode.valueOf(400))
                .body(problemDetail));
    }
}

字符串
除此之外,我还使用了Sring使用的ProblemDetail对象,因为我希望有一个一致的错误模型
例如

  • @ControllerAdvice处理自定义错误
{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "JSON decoding error: Cannot deserialize value of type `java.lang.Long` from String \"111A\": not a valid `java.lang.Long` value",
    "instance": "/v1/internal/tournament/create"
}

  • Spring误差
{
    "type": "about:blank",
    "title": "Method Not Allowed",
    "status": 405,
    "detail": "Supported methods: [POST]",
    "instance": "/v1/internal/tournament/create"
}

相关问题