ViewModels如何防止恶意数据库更改? [英] How do ViewModels prevent malicious database changes?

查看:139
本文介绍了ViewModels如何防止恶意数据库更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在查看问题此答案时why-do-we-use-viewmodels>为什么使用ViewModels?,我遇到了本节:

While looking at this answer to the question Why do we use ViewModels?, I came across this section:

视图不应包含任何非表示形式的逻辑"和您 不应信任该视图"(因为一个视图可以由用户提供). 提供一个Model对象(可能仍连接到活动对象 DatabaseContext)视图可能会对您的数据库进行恶意更改.

"A view should not contain any non-presentational logic" and "You should not trust the View" (because a View could be user-provided). By providing a Model object (potentially still connected to an active DatabaseContext) a view can make malicious changes to your database.

这到底指的是什么?如果我的模型和ViewModel中都有UserIdPassword,那么安全性从何而来?在控制器中进行某种检查?我们要检查什么?

What exactly does this refer to? If I have UserId and Password in my Model and my ViewModel, where does the security come in? Some kind of check in the controller? What do we check?

我们如何确定我们可以信任视图中的数据?这是由防伪令牌处理的吗?

How do we determine we can trust the data from the view? Is this handled by the antiforgery token?

推荐答案

我相信答案是指职位过多的问题.当您直接在视图中使用实体类时,尤其是如果您将发布的实体直接保存到数据库中时,恶意用户可以修改表单以发布他们不应修改的字段.

I believe the answer is referring to the over-post problem. When you utilize an entity class directly with your view, and particularly if you save that posted entity directly to your database, a malicious user could modify the form to post fields they should not be able to modify.

例如,假设您有一个允许用户编辑窗口小部件的表单.还要说您具有行级权限,这样用户只能编辑属于它们的窗口小部件.因此,我们的虚假恶意用户Joe编辑了一个允许他编辑的ID为123的小部件.但是,他决定要与Jane的小部件弄混,因此他将一个字段添加到名为Id的表单中,并将其值赋予简的小部件ID.当Joe然后发布小部件表单时,Jane的小部件将被更新.

For example, let's say you had a form that allows a user to edit widgets. Let's also say that you have row-level permissions, such that a user can only edit widgets that belong to them. So, Joe, our fictitious malicious user, edits a widget he's allowed to edit with id 123. But, he decides he wants to mess with Jane's widget, so he adds a field to the form named Id and gives it the value of Jane's widget id. When Joe then posts the widget form, Jane's widget is updated instead.

视图模型不仅用于解决此问题,而且从根本上可以解决该问题,因为从本质上讲,您不能直接将视图模型保存到数据库中.相反,必须先将视图模型的值映射到实体上,然后再将实体保存到数据库中.结果,您然后显式控制要映射的内容和不映射的内容,因此在上面的同一示例中,Joe更改id最终没有效果,因为您没有将其映射到实体上.

A view model is not solely for solving this problem, but it does basically negate the issue because, inherently, you cannot directly save the view model to the database. Instead, you must map the view model's values onto the entity, before saving the entity to the database. As a result, you then explicitly control what does and does not get mapped, so in the same example above, Joe changing the id ends up having no effect because you're not mapping that onto the entity.

实际上,这里的 real 问题是直接将用户发布的所有内容直接保存到数据库中.实际上,您仍然可以将实体类作为模型"提供给视图,但随后不保存发布的实例.取而代之的是,您然后创建一个实体的新实例,或者从数据库中重新拉一个实例,然后简单地将发布实例的值映射到该实例.同样,您不会映射Id之类的属性,因此Joe再次被挫败.换句话说,不是视图模型解决了问题,而是从不信任用户足以直接保存通过POST创建的解决问题的任何东西.

In truth, the real problem here is in directly saving anything posted by a user directly to the database. You could actually still feed your entity class to the view as the "model", but then not save the posted instance. Instead, you then create a new instance of the entity or pull an instance from the database fresh, and simply map the values from the posted instance over to that. Again, you wouldn't map a property like Id, so again Joe is foiled. In other words, it's not the view model that solves the problem, it's the never trusting a user enough to directly save anything created via a POST that solves the issue.

Microsoft以Bind属性的形式提供了另一种替代解决方案,它实质上允许您从模型绑定过程中包括/排除实体类上的某些属性(换句话说,忽略任何已发布的值).因此,例如,您可以通过使用[Bind(Exclude = "Id")]装饰操作上的参数来解决上面的问题,然后丢弃Id的所有已发布值.但是,Bind对于原因数量来说是可怕的,您不应实际使用它.始终改用视图模型,或者根本不要直接保存由Modelbinder创建的实体实例.

Microsoft gives another alternative solution in the form of the Bind attribute, which essentially allows you to include/exclude certain properties on an entity class from the modelbinding process (ignoring any posted values, in other words). So, for example, you could potentially solve the issue above by decorating the param on your action with [Bind(Exclude = "Id")], which would then discard any posted value for Id. However, Bind is horrible for a number of reasons, and you should not actually use it. Always use a view model instead, or simply don't ever directly save the entity instance created by the modelbinder.

这篇关于ViewModels如何防止恶意数据库更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆