Asp.net mvc 有什么比ASP.NET MVC中的隐藏表单字段更安全的吗?

Asp.net mvc 有什么比ASP.NET MVC中的隐藏表单字段更安全的吗?,asp.net-mvc,Asp.net Mvc,在ASP.NET MVC(默认路由)中,我希望使用如下URL返回带有表单的视图以编辑客户: /Customers/Edit/5 我需要使用CustomerId=5,但我不想允许客户更改它。现在我使用以下方法隐藏id: <%= Html.Hidden("CustomerId") %> 这实现了我想要的,但是我的印象是隐藏的表单变量是不安全的,可以由最终用户操纵 那么,允许客户编辑其信息而不编辑其ID的最佳方式是什么呢?您在浏览器端没有做任何真正的安全性。您可以将客户ID放入查询

在ASP.NET MVC(默认路由)中,我希望使用如下URL返回带有表单的视图以编辑客户:

/Customers/Edit/5
我需要使用
CustomerId=5
,但我不想允许客户更改它。现在我使用以下方法隐藏id:

<%= Html.Hidden("CustomerId") %>

这实现了我想要的,但是我的印象是隐藏的表单变量是不安全的,可以由最终用户操纵


那么,允许客户编辑其信息而不编辑其ID的最佳方式是什么呢?

您在浏览器端没有做任何真正的安全性。您可以将客户ID放入查询字符串中,但服务器应验证是否真的允许他们编辑该客户。如果没有,则返回错误。

在显示相应视图之前,请检查控制器操作(/Customers/Edit)中的权限。请注意,这里的问题根本不是隐藏字段:用户可以在浏览器中键入“”。因此,您必须在您的操作中检查用户是否真的被允许编辑请求的客户的详细信息,无论他如何调用该操作。

有两个方面。我不确定你直接问的是什么,但它们都很重要:

  • 对于任何给定用户,可能不允许他们编辑所有客户。因此,正如Dmitry所建议的那样,表单post的控制器操作需要查看他们试图编辑的客户,并验证登录用户实际上被允许编辑该客户。您可能还希望在控制器操作中执行类似的检查,该操作首先生成编辑表单,如果不允许他们编辑请求的客户,甚至不允许他们访问表单
  • 对于给定的用户和给定的客户,您可能不希望用户能够更改客户ID。如果您在POST controller操作中使用UpdateModel方法,您需要使用property whitelist参数并排除ID属性,以便用户不会更改ID。即使他们更改了隐藏字段的值,UpdateModel也会通过白名单忽略更改的值

    • 我也遇到了同样的问题,我相信解决方案包括使用代理密钥。在每个有ID列的表中,我还添加了一个作为Guid(SQL server中的uniqueidentifier)的键列。现在,当执行连接或任何内部逻辑时,我使用ID,但控制器都使用键。因为它是一个Guid,所以很难猜测另一条记录的Guid是什么


      或者(或除上述内容外),您可以根据

      对隐藏字段进行加密。我的解决方案是使用来自的防篡改代码。这样做的目的是为任何要防篡改的隐藏表单字段创建哈希:

      <%= Html.Hidden("CustomerId") %>
      <%= Html.Hidden("CustomerIdHash") %>
      
      
      

      提交表单时,Steven的代码会计算CustomerId的另一个散列,并确保它等于CustomerIdHash。如果是,则没有发生篡改。这是一个很棒的代码,值得一读。

      防篡改隐藏字段很好,但这仍然是一种隐蔽的安全性。最好通过保护控制器和操作来保护网站,更具体地说是MVC。然后,用户可以篡改他们想要的所有内容,他们将一事无成。

      我也有同样的担忧,我的解决方案是使用加密。
      您可以在服务器端加密CustomerId值,并将其作为查询字符串或隐藏字段发送,以便用户无法更改它,您可以随时解密它

      我了解如何配置控制器操作,以便只有授权用户才能查看特定ID的视图,但我不了解如何阻止用户更改该ID。例如,用户可能有权查看/Customers/Edit/10,但他们可以在提交表单时更改ID,并编辑他们最初无权查看的ID(例如/Customers/Edit/11)。我想我需要检查提交的表单,以确保ID是我首先发送给他们的。您必须检查当前登录的用户是否有权查看/编辑请求的ID。因此,在控制器操作中,您可以检索用户名(例如使用Thread.CurrentPrincipal.Identity.Name)并在数据库中检查是否允许该用户执行他尝试执行的操作(查看或编辑,取决于请求的操作)。因此,如果用户更改了ID,他仍然无法查看/编辑不允许的内容。事实上,他甚至没有理由试图改变身份证……确保你把那份杂烩腌了,否则你什么也得不到!(我相信这本书会更详细地解释这一点。)对,而且我假设您必须将FormCollection作为参数发送到post方法,以便可以在散列输入字段上运行比较,而不仅仅是将模型发送到post方法。或者,您可以向模型添加一个安全字段,以便将散列值发送回并绑定到您的模型。