Spring boot rest mvc json 解析器不会验证非法或具有尾随数据的输入 JSON 数据



在我的休息客户端中,我正在传递以下JSON请求数据:

  { 
    "jobName":"test1", 
    "source":{ "name":"prod1","type":"teradata"}, 
    "target":{ "name":"prod2","type":"teradata"}, 
    "objects":{ "name":"table1"}<br/>
    } 
junkdata ; @#%$@#% 

所以额外的"垃圾数据;@#%$@#%"未通过 REST 客户端或 Spring Jackson 开箱即用的消息转换器进行验证。
我确实调试了代码,Spring HttpServletRequest 主体具有完整的数据,包括垃圾数据。因此,它不会失败,Spring 会忽略垃圾数据并将起始 JSON 数据转换为 Java 对象。
我确实尝试在休息控制器调用 (@RestController( 中添加@JsonFormat for @RequestBody 等注释。但它没有验证似乎 Spring 开箱即用的消息转换器杰克逊没有正确验证传入的请求 JSON 数据。

现在这个问题(在跟踪令牌或数据上失败(在春季杰克逊 https://github.com/FasterXML/jackson-databind/issues/1583 中得到修复使用DeserializationFeature.FAIL_ON_TRAILING_TOKENS,下面是解决此问题的代码示例:

@Configuration
public class RestControllerConfiguration extends WebMvcConfigurationSupport
{
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
    converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
    }
}

在以不同的方式工作后,我使用 Google gson.jar 获得了解决方案,@Pete是的,我已经验证了无效的 JSON 输入。谷歌 gson API 正在正确验证它,我们需要使用自定义消息转换器在其余的 WebMvcConfigurationSupport 类中验证它。

@Configuration
@ComponentScan(basePackages = { "com.teradata.datamovement.rest.controllers",
        "com.teradata.rest.controller" })
public class RestControllerConfiguration extends WebMvcConfigurationSupport
{
       @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            log.debug("Adding custom message converter.");
            converters.add(new AbstractHttpMessageConverter<Object>(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")){
                @Override
                protected Object readInternal(Class<? extends Object> clazz,
                                              HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
                    try{
                        log.debug("Converting and validating the http request body data.");
                        String httpRequestBody = convertStreamToString(inputMessage.getBody());
                        log.debug("Http request body data:"+httpRequestBody);
                        return new Gson().fromJson(httpRequestBody, clazz);
                    }
                    catch(JsonSyntaxException e){
                        throw new HttpMessageNotReadableException("Invalid input JSON data: " + e.getMessage(), e);
                    } 
                }
                private String convertStreamToString(InputStream is) throws IOException {
                    if (is != null) {
                        Writer writer = new StringWriter();
                        char[] buffer = new char[1024];
                        try {
                            Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                            int n;
                            while ((n = reader.read(buffer)) != -1) {
                                writer.write(buffer, 0, n);
                            }
                        } finally {
                            is.close();
                        }
                        return writer.toString();
                    } else {
                        return "";
                    }
                }
                @Override
                protected boolean supports(Class clazz) {
                    return true;
                }
                @Override
                protected void writeInternal(Object t, HttpOutputMessage outputMessage)
                        throws IOException, HttpMessageNotWritableException {
                     outputMessage.getBody().write(new Gson().toJson(t).getBytes());
                }
            });
        }
}

但是我注意到的奇怪事情是,只有当我将其设置为匿名类或通过在同一文件中添加类时,它才能工作。如果我在此 RestControllerConfiguration.java 文件之外创建此自定义消息转换器,则它不会对其进行验证。下面是示例:

{
"jobName":"test1",
"source":{ "name":"prod1","type":"teradata"},
"target":{ "name":"prod2","type":"teradata"},
"objects":{ "name":"table1"}
}
junkdata ; @#%$@#%

这将得到验证,并会抛出错误,例如

{"message":"Invalid input JSON data: com.google.gson.stream.MalformedJsonException: Expected EOF at line 7 column 1; nested exception is com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Expected EOF at line 7 column 1"}

相关内容

  • 没有找到相关文章

最新更新