通过隐藏字段更新 .net core 2.2 中的模型而不会出现任何安全问题的正确方法

Proper way to update a model in .net core 2.2 without having any security issues through hidden fields

在创建脚手架项 (CRUD) Visual Studio 创建多个页面时,我对编辑页面有疑问。它在这里创建默认布局来更新您的模型,可以对其进行修改以满足您的需要。我看到的问题是它为您的 ID 创建了一个隐藏的输入字段。由于可以编辑输入控件,这不是安全问题吗?如果这是编辑的,当你按理论保存时它会更新一个不同的项目(因此是一个安全问题)?另外,如果我有第二个不应编辑的字段怎么办,例如 "CreatedBy" 我是否应该创建另一个隐藏字段?如果此字段也被编辑,我将失去我原来的 CreatedBy 用户。

此外,如果我删除这些隐藏的输入框以消除安全威胁,我面临的问题是自动验证将失败,因为它不会在模型上保留我的 Id 或 CreatedBy 用户。这也是更新时的一个问题,因为 Id 也会丢失。处理此问题的最佳和正确方法是什么?

下面是 visual studio 在您创建脚手架项 (CRUD) 时创建的自动代码示例:

...
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="Test.Id" />
    <div class="form-group">
        <label asp-for="Test.Created" class="control-label"></label>
        <input asp-for="Test.Created" class="form-control" />
        <span asp-validation-for="Test.Created" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Test.CreatedBy" class="control-label"></label>
        <input asp-for="Test.CreatedBy" class="form-control" />
        <span asp-validation-for="Test.CreatedBy" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="Test.Blahblah" class="control-label"></label>
        <input asp-for="Test.Blahblah" class="form-control" />
        <span asp-validation-for="Test.Blahblah" class="text-danger"></span>
    </div>
    <div class="form-group">
        <input type="submit" value="Save" class="btn btn-primary" />
    </div>
</form>
...

无论如何,我知道这是一些基本的东西,我一直在网上寻找这个问题的答案,但一直找不到。我已经找到了在验证期间检查特定属性的方法,但这仍然不能确保我不会丢失 Id 和 CreatedBy 字段,假设我删除了隐藏的输入。

似乎我唯一的选择就是遇到安全问题,但我拒绝相信这是正确的方法。无论如何感谢您的帮助!

有两种不同的东西:

  1. 要更新的 ID。

    无法阻止在更新数据集时将 Id 发送到服务器,因为 HTTP 是无状态的。使用 Session 或 TempData 之类的变通方法可能会阻止这种情况,但可能会给使用多个选项卡的用户带来不同的问题(例如,用户加载对象 A,然后在新选项卡中加载对象 B,然后将对象 A 保存在选项卡 1 中,这会导致 B将被覆盖,因为这是会话中加载的最后一个 ID)。

    这里的解决方案是验证和授权(例如Resource-based authorization)。


  1. 过度绑定/"mass assignment"

    当客户端发送的信息多于应有的信息时(例如 CreatedBy),就会出现此问题。 解决方案是使用仅包含可编辑字段的专用 ViewModel,或者使用 [Editable] 和 [BindNever] 等属性。这样模型绑定就不会绑定应该是只读的字段。 Here 是一篇解释该问题的博文。

    所以最好的方法是在发送给客户端之前删除不使用的隐藏字段(例如CreatedBy)(除非你想在某个地方显示它)。然后要更新模型,您使用 Id 从数据库加载数据,更新发布的可编辑属性(以及您要设置的其他字段,例如代码中设置的最后更新日期),然后保存模型。