首页 > 解决方案 > 验证可选字段的请求参数名称 - spring boot

问题描述

如果您有这样描述的端点:

@GetMapping("/hello")
public String sayHello(@RequestParam(name= "my_id", required=false) myId, @RequestParam(name= "my_name") myName){
    // return something
}

问题:

该端点的消费者可以在请求中发送无效的参数名称;

/hello?my_name=adam&a=1&b=2它会正常工作。

目标:

能够使用正确的方法来验证可选的请求参数名称。

实际解决方案:

我已经实现了一个解决方案(对我来说这不是正确的解决方案),我扩展了 aHandlerInterceptorAdapter并将其注册到WebMvcConfigurer

/**
 *
 * Interceptor for unknown request parameters
 *
 */
public class MethodParamNamesHandler extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ArrayList<String> queryParams = Collections.list(request.getParameterNames());

        MethodParameter[] methodParameters = ((HandlerMethod) handler).getMethodParameters();
        Map<String, String> methodParametersMap = new HashMap<>();
        if(Objects.nonNull(methodParameters)){
            methodParametersMap = Arrays.stream(methodParameters)
                    .map(m -> m.getParameter().getName())
                    .collect(Collectors.toMap(Function.identity(),Function.identity()));
        }
        Set<String> unknownParameters = collectUnknownParameters(methodParametersMap, queryParams);
        if(!CollectionUtils.isEmpty(unknownParameters)){
            throw new InvalidParameterNameException("Invalid parameters names", unknownParameters);
        }

        return super.preHandle(request,response,handler);
    }

    /**
     * Extract unknown properties from a list of parameters
     * @param allParams
     * @param queryParam
     * @return
     */
    private Set<String> collectUnknownParameters(Map<String, String> allParams, List<String> queryParam){
        return queryParam.stream()
                .filter(param -> !allParams.containsKey(param))
                .collect(Collectors.toSet());
    }
}

缺点:

该解决方案的缺点是它基于方法参数,它将采用名称myId而不是采用my_id,这可以通过将大写单词转换为蛇形来解决;但这不是一个好的解决方案,因为您可以拥有这样的东西:sayHello(@RequestParam(name= "my_id", required=false) anotherName)

问题: 是否有适当的方法来实现这一目标?

标签: springspring-bootspring-mvc

解决方案


推荐阅读