方案: (使用ASP.NET Web应用程序 - Core或MVC)
我为每个用户提供了一个包含Users
和Items
的数据库。
这意味着UserId
是foreign key
表中的Items
。
我从浏览器登录User
。我将Items
作为ItemViewModels
的列表,通过简单的api GET请求将其映射(AutoMapper)到ItemViewModels
。
我想通过简单的API调用更新其中一个项目(应该属于我 - 登录用户)。所以我通过PUT请求将修改后的项目作为ItemViewModel
发送回服务器。
第一种方法:
最简单的方法是在ItemId
中包含项目的数据库ID ItemViewModel
- 所以当我收到要更新为ItemViewModel
的项目时,我可以映射它返回数据库中的现有项目。
然而,这对我来说听起来非常不安全,因为任何人都可以使用任何ItemId
修改PUT请求,并影响不属于执行请求的用户的项目。这种方法有什么我想念的吗?
第二种方法:
请勿在{{1}}中传递数据库PK ItemId
。
而是使用其他形式的标识:假设用户ItemViewModel
有10个项目。它们使用名为X
的属性(也存在于数据库中)从1到10编号。
然后,我可以在UserItemId
中传递此UserItemId
,当我将其恢复时,我可以将其映射到数据库中的现有项目(如果请求一切正常)或丢弃它如果ItemViewModel
与登录用户的项目中的任何内容都不匹配,则拒绝该请求。
有人使用这种方法吗?
优点:
用户只能访问自己的项目,并且不会影响其他任何人,因为它不知道实际的项目ID(主键),并且任何修改仅限于它的项目。
缺点:
必须在服务器端实施大量额外管理才能使用此方法。
还有其他方法吗?
请考虑上述情况适用于数据库中客户端实现可以CRUD的所有实体,因此不仅仅是上述的简单情况。
建议的解决方案应适用于整个应用数据。
我知道这个问题已被问到here和here但是第一个问题没有令人满意的答案,我认为第二个问题并不适用于我的情况,因为它只是处理UserId。
感谢。
修改
请将上面的UserItemId
视为聚合根,其中包含多个复杂Item
,每个复合subItems
都包含一个表格。这个问题适用于主要Item
。这意味着每个subItem
都作为ViewModel传递给客户端。
我应该提及有关进一步确保更新请求的安全性:
对于第一种方法,我可以轻松检查是否允许用户更改项目。但我也应该为所有subItems
执行此操作。
对于第二种方法,我可以检查用户是否可以按如下方式更新Item
:我得到传入的ViewModel的userItemId
- >我从数据库中获取所有已登录用户的项目并尝试查找与相同userItemId
的匹配项,如果我获得了点击,则继续进行更新。
答案 0 :(得分:0)
如果您只隐藏ID,我认为您的应用程序不安全。
在更改数据库实体之前,必须检查是否允许用户更改实体。
在您的情况下,如果您的身份验证用户中的Id
是您商品中的UserId
,则应该进行检查。
如果您的ViewModel与您的API相似或相同,则可以在控制器中使用FilterAttribute。