如何防止在 ASP.NET Core 的 Razor 视图 HTML 中禁用或只读输入字段的模型绑定?

Posted

技术标签:

【中文标题】如何防止在 ASP.NET Core 的 Razor 视图 HTML 中禁用或只读输入字段的模型绑定?【英文标题】:How to prevent model binding of disabled or readonly input fileds in Razor view HTML in ASP.NET Core? 【发布时间】:2021-12-10 07:50:22 【问题描述】:

所以我有复杂的对象应该显示在页面上。对于某些访问角色的用户,应该禁用(或只读)此对象的某些属性。但是,我注意到,如果我在 devtools 中编辑此 <input disabled .../> 并删除 disabled 属性并添加任意文本,那么模型绑定器将很高兴地获取此值并将其放入表单模型中,当通过 OnPost 操作提交时。

这里是示例代码:

    <form method="post">
        <div class="form-group col-sm-6">
            <label asp-for="FormModel.FirstName" class="control-label">First Name</label>
            <input asp-for="FormModel.FirstName"
                   disabled="disabled"
                   class="form-control"
                    />
        </div>
        <div class="form-group col-sm-6">
            <label asp-for="FormModel.LastName" class="control-label">Last Name</label>
            <input asp-for="FormModel.LastName"
                   class="form-control"
                   />
        </div>
        <input type="submit" value="Save" class="btn btn-primary" />
    </form>

以及页面模型:

    public class IndexModel : PageModel
    
        private readonly MyDbMock _myDb;

        [BindProperty]
        public FormModel FormModel  get; set; 

        public IndexModel(MyDbMock myDb)
        
            _myDb = myDb;
        

        
        public void OnGet()
        
            FormModel = new FormModel
            
                FirstName = _myDb.FormModel.FirstName,
                LastName = _myDb.FormModel.LastName
            ;
        
        public IActionResult OnPost()
        
            _myDb.FormModel = FormModel;
            return RedirectToAction(nameof(OnGet));
        
    

    public class FormModel
    
        public string FirstName  get; set; 
        public string LastName  get; set; 
    

    public class MyDbMock
    
        public FormModel FormModel  get; set;  = new FormModel
        
            FirstName = "John",
            LastName = "Smith"
        ;
    

当我第一次打开此页面时,我在禁用的输入中看到John,并带有First name 标签。这可以。然后,当我单击Save 时,我的OnPost 方法将获得FormModel 对象,其中FirstName 为空。这反映在更新的页面中。可以防止这种情况并告诉模型绑定器不要触摸此属性吗? IE。提交表单时将其保留为John,并且因为它被禁用而不将其设置为null

我遇到的另一个问题是高级用户可以从First Name 输入中删除disabled 属性并提交任意值。这也可以通过告诉模型绑定器与上述相同的事情来防止吗?例如。在GET 请求中发送First Name 字段时保持原样,没有更新。

这是所有这些的演示:

我知道我可以通过阻止更新禁用字段来在后端代码中处理此问题。但是,如果它存在,我正在寻找一些更优雅和声明性的方式。在我的主项目中,表单模型非常复杂,并且在对象中包含对象,因此理想情况下,我想跳过为此操作处理程序添加额外的逻辑。

【问题讨论】:

永远不要相信用户。在您的OnPost 中,您必须重新检查您的授权。或者您可以创建一个自定义的IModelBinderProvider / IModelBinder,使用属性为您检查授权策略。 【参考方案1】:

尝试添加隐藏输入绑定FormModel.FirstName,并更改禁用输入的名称,使禁用输入的值不会绑定到FormModel.FirstName

<form method="post" >
    <div class="form-group col-sm-6">
        <label asp-for="FormModel.FirstName" class="control-label">First Name</label>
        <input asp-for="FormModel.FirstName" name="FirstName"
               disabled="disabled"
               class="form-control" />
        <input asp-for="FormModel.FirstName" hidden/>
    </div>
    <div class="form-group col-sm-6">
        <label asp-for="FormModel.LastName" class="control-label">Last Name</label>
        <input asp-for="FormModel.LastName"
               class="form-control" />
    </div>
    <input type="submit" value="Save" class="btn btn-primary" />
</form>

结果:

【讨论】:

以上是关于如何防止在 ASP.NET Core 的 Razor 视图 HTML 中禁用或只读输入字段的模型绑定?的主要内容,如果未能解决你的问题,请参考以下文章

防止在 Asp.Net Core ViewComponents 中加载多个 JavaScript 脚本

防止 AddRedirectToWwwPermanent() 在 ASP.NET Core 2.1 中将“www”添加到 *.azurewebsites.net 的前面

防止在 asp.net core 2.2 中重定向到 /Account/Login

Asp.Net Core 通过中间件防止图片盗链

防止在后端ASP.NET Core 3中提交双重形式的提交。*

Redis系列文章总结:ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁