首页 > 解决方案 > 在.net core 2.2中更新模型的正确方法,而不会通过隐藏字段出现任何安全问题

问题描述

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

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

下面是创建脚手架项目 (CRUD) 时由 Visual Studio 创建的自动代码示例:

...
<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 字段,假设我删除了隐藏的输入。

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

标签: c#.netasp.net-core.net-coreasp.net-core-2.2

解决方案


有2个不同的东西:

  1. 要更新的 ID。

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

    这里的解决方案是验证和授权(例如基于资源的授权)。


  1. 过度绑定/“批量分配”

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

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


推荐阅读