拒绝具有额外查询参数的GET请求。

4

我有一个HTTP GET端点,可以接受一些查询参数:

@GetMapping("/cat")
public ResponseEntity<Cat> getCat(@RequestParam("catName") String catName){ ...

如果客户端发送了额外的查询参数,端点将会忽略它们。
GET .../cat?catName=Oscar                Getting Oscar
GET .../cat?catName=Oscar&gender=male    Getting Oscar
GET .../cat?catName=Oscar&x=y            Getting Oscar

我希望您能够拒绝发送额外查询参数的HTTP请求。
GET .../cat?catName=Oscar                OK
GET .../cat?catName=Oscar&gender=male    Reject (HTTP error code XYZ)
GET .../cat?catName=Oscar&x=y            Reject (HTTP error code XYZ)

我可以更改方法的签名以接受一个map,并验证map中的值,如此处建议。

是否有一种方法可以保持更清晰和自我解释的方法签名来完成这个任务?


1
如果您在控制器方法中添加了注释@RequestParam和正确的字段,则每个具有更多或不同参数的请求都将被拒绝。我认为您不需要做任何事情,除非您想要自定义异常,您可以创建一个并发送特定的错误代码以处理该情况。 - A L
您还可以创建其他方法,其中包含不可接受的参数,并在这些方法中返回自定义错误代码。 - behrad
1个回答

1

您可以尝试实现一个HandlerInterceptor,并在preHandle()中验证此规则。如果请求包含在控制器方法中未定义的查询参数,则只需抛出特定类型的Exception并配置@ControllerAdvice来处理此异常。例如:

public class FooHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;

            Set<String> allowQueryParams = Stream.of(hm.getMethodParameters())
                    .map(p -> p.getParameterAnnotation(RequestParam.class))
                    .map(req -> req.value())
                    .collect(toSet());

            for (String currentRequestParamName : request.getParameterMap().keySet()) {
                if (!allowQueryParams.contains(currentRequestParamName)) {
                    throw new FooRestException();
                }
            }
        }

        return true;
    }
}

使用@ControllerAdvice来处理异常:

@ControllerAdvice
public class FooExceptionHandler {

    @ExceptionHandler(FooRestException.class)
    public ResponseEntity<Object> handle(FooRestException ex) {
        return new ResponseEntity<>("Some query parameter are not defined", HttpStatus.BAD_REQUEST);
    }
}

最后将FooHandlerInterceptor注册以使用它:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FooHandlerInterceptor());
    }
} 

我只是给你展示了这个想法。如果你希望这种检查仅适用于特定控制器方法,你可以进一步调整 HandlerInterceptor 中的代码。


尝试按照你的方法,但在'.map(req - > req.value())'行中,“req”始终为空,即使有一个接受@valid对象的post方法。 - VirtualNomad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接