PUT和POST在未知属性上失败Spring不同的行为 [英] PUT and POST fail on unknown properties Spring different behavior

查看:126
本文介绍了PUT和POST在未知属性上失败Spring不同的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring Data Rest存储库编写Spring Boot应用程序,如果请求主体包含具有未知属性的JSON,我想拒绝访问资源。简化实体和存储库的定义:

I am writing Spring Boot application using Spring Data Rest repositories and I want to deny access to resource if request body contains JSON that has unknown properties. Definition of simplified entity and repository:

@Entity
public class Person{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String firstName;
    private String lastName;

    /* getters and setters */
}

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends CrudRepository<Person, Long> {}

我使用Jackson的反序列化功能来禁止JSON中的未知属性。

I use Jackson's deserialization feature to disallow unknown properties in JSONs.

@Bean 
public Jackson2ObjectMapperBuilder objectMapperBuilder(){
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.failOnUnknownProperties(true);
    return builder;
}

当我发送POST请求时,一切都按预期工作。当我使用有效字段时,我得到正确答案:

When I send POST requests everything works as expected. When I use valid fields I get correct response:

curl -i -x POST -H "Content-Type:application/json" -d '{"firstName": "Frodo", "lastName": "Baggins"}' http://localhost:8080/people
{
  "firstName": "Frodo",
  "lastName": "Baggins",
  "_links": {...}
}

当我发送带有未知字段的JSON时,应用程序会抛出预期的错误:

And when I send JSON with unknown fields application throws expected error:

curl -i -x POST -H "Content-Type:application/json" -d '{"unknown": "POST value", "firstName": "Frodo", "lastName": "Baggins"}' http://localhost:8080/people
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "unknown" (class Person), not marked as ignorable (2 known properties: "lastName", "firstName")

使用有效JSON时的PUT方法也会返回正确的响应。但是,当我向未知字段发送PUT请求时,我希望Spring抛出错误,而不是那样,Spring更新数据库中的对象并返回它:

PUT method when using valid JSON returns correct response as well. However when I send PUT request with unknown field I expect Spring to throw error but instead of that, Spring updates object in database and returns it:

curl -i -x PUT -H "Content-Type:application/json" -d '{"unknown": "PUT value", "firstName": "Bilbo", "lastName": "Baggins"}' http://localhost:8080/people/1
{
  "firstName": "Bilbo",
  "lastName": "Baggins",
  "_links": {...}
}

只有当数据库中没有对象时才会抛出错误给定id:

The error is thrown only when there is no object in database with given id:

curl -i -x PUT -H "Content-Type:application/json" -d '{"unknown": "PUT value", "firstName": "Gandalf", "lastName": "Baggins"}' http://localhost:8080/people/100
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "unknown" (class Person), not marked as ignorable (2 known properties: "lastName", "firstName")

是预期的行为还是错误Spring Data Rest?如果将具有未知属性的JSON传递给应用程序,无论请求方法是什么,我怎么能抛出错误?

Is it expected behavior or a bug in Spring Data Rest? How can I throw an error when JSON with unknown properties is passed to application no matter what request method is?

我'通过修改 http://spring.io/guides/gs/accessing-data-rest/ <重现此行为/ a> ,我唯一的变化是 Jackson2ObjectMapperBuilder ,此项目中没有其他控制器或存储库。

I've reproduced this behavior by modifying http://spring.io/guides/gs/accessing-data-rest/ , the only change I've made is Jackson2ObjectMapperBuilder , no other controllers or repositories are in this project.

推荐答案

我认为你观察到的行为是设计的。当发布POST时,您正在创建资源,因此JSON被反序列化为您的实体类型,而Jackson正在执行此任务。

I think the behaviour you are observing is by design. When a POST is issued you are creating the resource so the JSON is deserialised into your entity type and Jackson is performing this task.

PUT在弹簧数据休息时的工作方式不同。有趣的部分在 PersistentEntityResourceHandlerMethodArgumentResolver.readPutForUpdate 中处理。

A PUT is working differently in spring data rest. The interesting part is handled in PersistentEntityResourceHandlerMethodArgumentResolver.readPutForUpdate.

json被读入 JsonNode ,从数据存储中读取实体,然后在 DomainObjectReader.doMerge 中实现迭代json字段。它将json应用于实体并稍后将其保存在控制器实现中。它还会丢弃持久化实体中不存在的所有字段:

The json is read into a JsonNode, the entity is read from the data store and then in DomainObjectReader.doMerge the implementation iterates over the json fields. It applies the json to the entity and saves it later in the controller implementation. It also discards all the fields that do not exist in the persistent entity:

if (!mappedProperties.hasPersistentPropertyForField(fieldName)) {
    i.remove();
    continue;
}

这是我对阅读代码的理解。我想你可以说这是一个错误。您可以尝试在春季数据休息时报告它 - https://jira.spring.io/browse/DATAREST。据我所知,无法自定义此行为。

This is my understanding from reading the code. I think you could argue that this is a bug. You could try to report it at spring data rest`s jira - https://jira.spring.io/browse/DATAREST. As far as I know there is no way to customise this behaviour.

这篇关于PUT和POST在未知属性上失败Spring不同的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆