我正在学习Asp MVC 5并面临这样的问题。使用脚手架visual studio为我创建更新控制器和视图。编辑值时,我注意到它使用隐藏来识别当前记录。例如:
http://localhost:61551/StoreManager/Edit/6
如果使用开发工具检查页面 - 您将找到值为" 6"的隐藏输入。
<input data-val="true" data-val-number="The field AlbumId must be a number." data-val-required="The AlbumId field is required." id="AlbumId" name="AlbumId" type="hidden" value="6">
在视图中我们可以看到ASP添加代码来生成隐藏输入
@Html.HiddenFor(model => model.AlbumId)
我可以轻松地将其修改为任何其他值,然后当我单击“保存”时,ASP会更新完全不同的记录。因此,黑客可能很容易破坏您的所有数据库。有没有办法阻止这种情况或使用不同的方法或验证它?
谢谢!
答案 0 :(得分:3)
这里的根本问题是您的网站信任网络浏览器提供的任何输入。无论输入来自隐藏字段,还是通过URL,或者某些非隐藏字段(例如,您可以想象一个UI,其中有一个下拉选择器可以让您输入),也存在同样的问题选择要修改的数据项,或者即使在网页上的JavaScript发送到后端的某些JSON消息中标识了记录。
所以你描述的问题与这个隐藏字段的特定细节没有任何关系,也与你使用ASP.NET的事实有任何关系, VS搭建应用程序的方式也不是特别的。您可以更改任何这些详细信息并仍然存在问题,因为恶意用户可以在请求中伪造任何内容。隐藏字段并不比任何其他类型的输入更难或更容易伪造。
从安全角度来看,您需要将来自客户端的所有数据视为可疑。确定此类输入是否有效的规则是特定于应用程序的,这就是为什么脚手架代码不会(也不能)尝试处理此问题的原因。
唯一的解决方案是使用某种机制来确定是否允许发送请求的用户执行请求要求执行的操作。如果你实现了这一点,那么最终用户故意更改ID并不重要:如果某个特定用户有权编辑id为6的记录或id为7的记录,那么如果他们编辑6和将其改为7,即他们的决定 - 他们可以编辑记录7并选择这样做;他们以一种奇怪的方式做到了,但这就是他们的了望。如果用户有权编辑6而不是7,并且他们尝试将id更改为7,那么您的服务器应该使用403(禁止)响应代码拒绝该请求。
这意味着您需要一些方法来识别用户(或至少有一些方法来了解某些关于他们的信息 - 足以确定他们有权做什么;在某些情况下,这可能就足够了要知道用户已成功通过某些安全授权进行身份验证 - 对于某些操作,合理的安全策略可能只是信任所有经过身份验证的用户或属于特定安全组的所有用户。并且您需要某种方式来确定在识别出特定实体后,特定实体是否允许用户使用特定操作。
通常,这意味着让用户登录(并且有各种各样的方法可以执行此操作 - 您的应用程序可能在某个具有某种单点登录系统的组织内部运行,或者您可以遵循一个外部ID提供商,如Google,Facebook或Azure Active Directory,或者您可以自己管理帐户 - 例如,ASP.NET可以为您管理SQL Server中的用户帐户。而且你需要决定你的安全策略实际上是如何工作的,这是一个开放式的东西,我甚至都不会尝试提供exaples,然后你需要编写代码执行该政策。
从VS获得的基本脚手架应用程序并不能完成所有这些,因为有很多不同的方法可以接近它。它可以执行部分操作 - 您可以告诉它配置具有用户帐户支持的应用程序(例如,如果您需要,它可以在您创建项目时设置基于SQL Server的帐户管理,或者它可以将其设置为使用AAD,或通过集成的Windows身份验证进行单点登录)。但是,你仍然需要决定你想要什么样的安全策略。如果你想要一个非常基本的模型,例如&#34;只有经过身份验证的用户才能访问#34;,那么你可以将[Authorize]
自定义属性放在控制器上。但是,如果您想要实体级安全性(例如,确定允许谁修改任何特定实体的规则),那么您需要编写代码来实现这一点。
答案 1 :(得分:0)
有很多方法可以解决这个问题。一种方法是使用User roles来限制谁可以访问各种方法(如编辑)。
您可以使用以下代码:
if (User.IsInRole("Administrators"))
{
// TODO
}
或者你可以这样使用Authorize attributes:
[Authorize(Roles="Administrators")]
public class AdminController : Controller
{
// TODO
}
或者,这些也可以放在控制器内的特定方法上:
[Authorize(Roles="Administrators")]
public ActionResult Edit(Album model)
{
// TODO
}
当您拥有广泛定义的角色而不是谁可以访问的内容时,这些是更好的解决方案,但假设您拥有一个服务,每个用户都可以登录并管理自己的项目。您还可以向模型/表格添加字段以表示该项目所属的人员,例如:
if (albumModel.UserName == HttpContext.Current.User.Identity.Name)
{
// allow user to edit if it is his item
}
您还可以看到如何将这些结合起来,例如:如果允许管理员编辑用户的专辑,您可以先检查用户是否属于管理员角色,否则检查是否是该用户的专辑等。