在查看这个答案的问题我们为什么要使用ViewModels?时,我看到了以下部分:
“视图不应该包含任何非表示逻辑”和“您不应该信任视图”(因为视图可以由用户提供)。通过提供模型对象(可能仍然连接到活动的DatabaseContext),视图可以对数据库进行恶意更改。
这究竟指的是什么?如果我的模型和Password中都有UserId和Password,那么安全性在哪里呢?在控制器里登记了吗?我们要查什么?
如何确定我们可以信任视图中的数据?这是由防伪令牌处理的吗?
发布于 2017-07-25 16:24:04
我相信答案是指过职问题。当您使用视图直接使用实体类时,特别是如果您将已发布的实体直接保存到数据库中,恶意用户可能会修改表单以发布他们不应该修改的字段。
例如,假设您有一个允许用户编辑小部件的表单。我们还假设您具有行级权限,因此用户只能编辑属于它们的小部件。因此,我们虚构的恶意用户Joe编辑了一个允许他用id 123编辑的小部件。但是,他决定要处理Jane的小部件,因此他向名为Id的表单中添加了一个字段,并给出了Jane的小部件id的值。然后,当Joe发布小部件表单时,会更新Jane的小部件。
视图模型并不仅仅是为了解决这个问题,但是它基本上否定了这个问题,因为从本质上说,您不能将视图模型直接保存到数据库中。相反,在将视图模型的值保存到数据库之前,必须将视图模型的值映射到实体上。因此,您将显式地控制哪些是映射的,哪些不是映射的,因此在上面的同一个示例中,Joe更改id最终没有效果,因为您没有将它映射到实体上。
事实上,这里真正的问题是直接保存用户直接发布到数据库的任何内容。实际上,您仍然可以将实体类作为“模型”提供给视图,但不能保存已发布的实例。相反,您可以创建实体的一个新实例,或者从数据库中取出一个新实例,然后简单地将已发布实例的值映射到该实例。再说一遍,您不会映射像Id这样的属性,因此Joe同样被挫败了。换句话说,解决问题的不是视图模型,而是永远不信任用户,无法直接保存通过帖子创建的任何解决问题的内容。
Microsoft以Bind属性的形式给出了另一种替代解决方案,它允许您从模型绑定过程中包含/排除实体类上的某些属性(换句话说,忽略任何已发布的值)。因此,例如,您可以通过用[Bind(Exclude = "Id")]装饰操作上的param来解决上面的问题,这样就会丢弃Id的任何posted值。然而,Bind对于理由数来说是可怕的,您不应该实际使用它。始终使用视图模型,或者根本不直接保存由模型绑定器创建的实体实例。
https://stackoverflow.com/questions/45307963
复制相似问题