在查看问题this answer的Why do we use ViewModels?时,我看到了这一部分:
“视图不应包含任何非表示逻辑”和“你 不应该信任视图“(因为视图可以由用户提供) 提供一个Model对象(可能仍然连接到一个活动的 DatabaseContext)视图可以对您的数据库进行恶意更改。
这究竟是指什么?如果我的模型和我的ViewModel中有UserId
和Password
,那么安全性在哪里?在控制器中进行某种检查?我们检查什么?
我们如何确定我们可以信任视图中的数据?这是由防伪令牌处理的吗?
答案 0 :(得分:3)
我认为答案是指过头问题。当您直接在视图中使用实体类时,特别是如果将发布的实体直接保存到数据库中,恶意用户可以修改表单以发布他们无法修改的字段。
例如,假设您有一个允许用户编辑小部件的表单。我们还假设您具有行级权限,这样用户只能编辑属于它们的小部件。所以,Joe,我们虚构的恶意用户,编辑了一个他允许用id 123编辑的小部件。但是,他决定要混淆Jane的小部件,所以他在名为Id
的表单中添加了一个字段并给它Jane的小部件ID的值。当Joe随后发布小部件表单时,Jane的小部件会更新。
视图模型不仅仅是为了解决这个问题,而且它确实基本上否定了这个问题,因为从本质上讲,你不能直接将视图模型保存到数据库中。相反,在将实体保存到数据库之前,必须将视图模型的值映射到实体。因此,您可以显式控制要映射的内容和未映射的内容,因此在上面的相同示例中,Joe更改id最终没有效果,因为您没有将其映射到实体上。
实际上,真正的问题在于直接将用户发布的任何内容直接保存到数据库中。实际上,您仍然可以将实体类作为“模型”提供给视图,但不保存已发布的实例。相反,您可以创建实体的新实例或从数据库中提取实例,并简单地将已发布实例中的值映射到该实例。同样,你不会映射像Id
这样的属性,所以Joe再次被挫败。换句话说,它不是解决问题的视图模型,它永远不会信任用户直接保存通过POST解决问题所创建的任何内容。
Microsoft以Bind
属性的形式提供了另一种替代解决方案,它基本上允许您从模型绑定过程中包含/排除实体类中的某些属性(换句话说,忽略任何已发布的值)。因此,举例来说,您可以通过使用[Bind(Exclude = "Id")]
修改您的操作的参数来解决上述问题,然后放弃Id
的任何已发布值。但是,对于number of reasons,Bind
是可怕的,你实际上不应该使用它。始终使用视图模型,或者根本不直接保存由模型绑定器创建的实体实例。