我使用了一个非常普通的spring-boot-starter-data-rest
设置并启用了PATCH
方法,一切正常,但我有一个安全问题,我想知道什么是推荐的缓解方法。
问题是PATCH
path
允许从不同的端点更新可访问的实体。所以,假设我有一个comments
端点和一个article
端点。每个评论与它的文章都有一个对一的关联。一个有权限编辑评论的用户可以这样做:
PATCH http://some.domain.foo/api/comments/1234
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/article/title", "value": "foobar2" }
]
从而改变文章的标题!!
显然情况不妙。
在这种情况下,对于API的其他部分,与"article"的关联需要是可遍历的,但它必须是只读的。
那么......我该如何在Spring实现这一点呢?
拦截请求?实现一个句柄方法?从头开始编写自己的控制器?
谢谢!
2条答案
按热度按时间but5z9lq1#
看起来spring-data-rest上的当前实现将路径转换为SpEL以直接在bean上应用值。
考虑以下选项:
@JsonIgnore
和其他Jackson注解,并且也会区别对待关联。ResourceProcessor
中提供自定义链接。另外,如果你使用JPA,并且
Comment.article
是用@ManyToOne
注解的,那么要确保关联上没有级联,即使文章对象是用patch修改的,它也不会和注解一起保存。d7v8vwbk2#
Spring Data Rest中最近有一个修复:
https://github.com/spring-projects/spring-data-rest/issues/2177
解决此问题的提交是:
https://github.com/spring-projects/spring-data-rest/commit/5d0687d1a1bb9a84264ecb4cd088907837c382d3
从快速阅读来看,这似乎是在检查当将JSON补丁应用于实体时,是否使用Jackson检查路径是否可以访问(读/写)。
这应该会阻止用户在JSON补丁中指定路径,而这些路径通常不会通过POST/GET请求(通过Jackson直接Map到实体)暴露。我认为,如果您将文章标记为可从评论读取,并将title属性标记为可写,那么新代码应该允许这样做。或者,我认为这就是
org.springframework.data.rest.webmvc.json.patch.JsonPointerMapping#verify
试图做的。因此,如果你在评论中将文章标记为不可通过Jackson读取(getter上的
@JsonIgnore
),那么JSON补丁不应该允许通过评论设置文章的标题。关联仍然存在,只是不会通过JSON序列化暴露出来,我不确定这是否会给你的应用程序带来问题。该变更在Spring Data Rest 4.0.0中发布,该版本是Sping Boot 3.0.2中Spring Data 2022.0.1的一部分。
https://github.com/spring-projects/spring-data-rest/releases/tag/4.0.0https://github.com/spring-projects/spring-data-bom/releases/tag/2022.0.1https://github.com/spring-projects/spring-boot/releases/tag/v3.0.2