如何防止实体关系发生变化?
Posted
技术标签:
【中文标题】如何防止实体关系发生变化?【英文标题】:How to prevent changes of entity relationships? 【发布时间】:2018-10-30 06:30:36 【问题描述】:我正在使用 Spring Boot 通过 JPA 在我们的数据库中存储复杂的 json 结构。
json 结构的根代表一个“House”对象。一个“房子”对象包含几个“家具”。例如:
House ID: 4711
|- Furniture: ID 4712 (with confidential information)
用户对某些房屋及其所有“家具”拥有读/写权限。
我的问题是,如果用户知道它们的主键,则通过 REST-API,用户可以从其他房屋“窃取”家具;有这样的要求:
POST http://localhost:8080/house
houseId: 99991337,
furnitures: [
furnitureId: 4712,
...
]
这导致:
House ID: 4711
|- empty!
House ID: 99991337
|- Furniture 4712 (with confidential information)
尽管用户没有访问 4711 号房屋的权限,但他将家具 4712 与 4711 号房屋“取消链接”,而是将其链接到 99991337 号房屋。
如何禁止更换家具之家?
在 JPA 实体中,存在从房屋到家具的双向 OneToMany-Relationship。我想也许在数据库中搜索任何传入请求的家具,检查所有这些请求的所有权限。但我宁愿只检查房子的许可(因为在现实生活中,我有更多的实体,比如家具)
【问题讨论】:
houses
的权限是如何定义的?
@htshame 我添加了一个授权示例。在我的实际应用程序中,所有这一切都要复杂得多 - 但我相信,这个简化示例的一个好的答案将为我的复杂现实世界应用程序提供良好的服务。
你的意思是一些ID的家具只能使用一次?
@Akceptor 是的,一件家具应该属于完全一个房子,并且应该由该房子私人拥有。只有被允许查看/编辑房屋的用户才能查看/编辑其家具。
那么,在现有条件下,用户每次用POST http://localhost:8080/house
创建房子都可以创建新家具?
【参考方案1】:
如果我的理解是正确的,只需通过请求中提供的userId
和houseId
搜索权限表即可。
如果匹配,则用户有权更改houseId
。
根据权限,您可以将houseId
设置为您将要保存到数据库的对象,也可以不设置。
如果您仍希望用户更改furniture data
,则可以通过为new Furniture()
对象提供furnitureId
和text
来仅保存furniture
实体。
【讨论】:
谢谢,我认为这个解决方案确实对我有用。但是我更喜欢开箱即用的解决方案,它不需要首先查询家具表(在我的现实世界应用程序中,除了家具之外,我还有许多不同的实体类,都与房屋有直接或间接的关系) .您是否知道任何 Annotation 或类似的,隐含地为我检查? 我想这取决于您的安全层实现。您可能想查看spring-security
中的@PreAuthorise
注释,它可能会有所帮助。【参考方案2】:
我认为您可以尝试将处理程序放在带有注释@HandleBeforeSave
和@RepositoryEventHandler
的Furniture
实体表的更新上,并且在此处理程序中,您只能查询此Furniture
实体并检查它属于哪个House
。然后决定如何处理这个更新请求
【讨论】:
【参考方案3】:如果以下陈述成立:
Yes, a furniture should belong to exactly one house and should be privately be owned by that house. Only those users permitted to see/edit the house should be able to see/edit its furniture.
在我看来,这意味着你不应该被允许用已经连接到另一所房子的家具来建造房子(业务要求)。
在创建房子之前,我会先检查家具是否不属于另一所房子(保持数据完整性),如果是则抛出异常。我看到这种情况发生在业务层,它将满足任何可能损害数据/需求的外部边界调用。
您可以将其移到业务层之外,但您可能会在每个频道重复代码或错过一/两个频道。
【讨论】:
感谢您的回答 - 这似乎是一个很好且干净的解决方案。但是,由于我的House
附加了数十个实体类,这将花费大量代码。【参考方案4】:
首先,您的请求结构不正确。出于这样的安全原因,您不能向用户询问他的用户 ID、家庭 ID 等。您需要在后台处理它而不依赖于用户请求。
但是对于这种情况,您可以简单地使用 select insert 更改插入语句。加入权限表以选择语句以检查给定的 id 是否附加到相关用户。如果没有插入的用户试图插入非法 id。
【讨论】:
以上是关于如何防止实体关系发生变化?的主要内容,如果未能解决你的问题,请参考以下文章
当SwiftUI中的相关实体发生变化时,如何更新@FetchRequest?
面试题--如何防止sql注入,使用PreparedStatement的预编译,传入的内容就不会和原来的语句发生任何匹配的关系,达到防止注入的方法
由于 Illuminate\Queue\SerializesAndRestoresModelIdentifiers,Job 类内部的加载关系发生了变化