【问题标题】:MVC4 Razor Looses UserID if Unbound如果未绑定,MVC4 Razor 会丢失用户 ID
【发布时间】:2012-10-02 00:14:06
【问题描述】:

目前,我正在 MVC4 中创建一些用户配置文件编辑表单,为了进行测试,我将 UserId 属性呈现为表单上的只读文本框,如下所示:

<li>
    @Html.LabelFor(model => model.UserId)
    @Html.TextBoxFor(model => model.UserId, new { @readonly="readonly"})
</li>

当我接近完成编辑表单时,我删除了这个文本框,因为它只是用完房地产。完成此操作后,保存时发送回控制器的模型具有整数默认值 0,然后实体框架因无法更新任何行而崩溃。所以我在表单中添加了这个:

<li>
    @Html.HiddenFor(model => model.UserId, new { @readonly="readonly"})
</li>

这是一个安全的举动吗?我应该将 ViewBag 用于这样的事情吗?在个人资料详细信息页面上,我呈现了一个编辑按钮,如下所示:

@Html.ActionLink("Edit", "Edit", new { id=Model.UserId })

表示在链接中呈现 UserId。这是安全可靠的还是我需要重新考虑如何在 UI 中移动模型和 ID?

TIA,

【问题讨论】:

    标签: asp.net-mvc data-binding razor model


    【解决方案1】:

    这是一个安全的举动吗?

    这将完成将 id 发送到服务器的工作。只需去掉 readonly="readonly" 属性,这对于隐藏的输入几乎没有意义。

    我应该将 ViewBag 用于这样的事情吗?

    这不会改变任何安全性。任何用户仍然可以输入他想要的任何 id。无论您使用隐藏字段还是 ActionLink,您仍然将 id 作为纯文本发送到服务器,任何人都可以伪造请求并输入他想要的任何 id。因此,如果您的站点使用某种形式的身份验证,则在尝试对其执行任何操作之前,您必须在服务器端绝对检查您实际收到的 id 是属于当前经过身份验证的用户的资源。否则,一些经过身份验证的用户可以提供属于另一个用户的资源的 id 并能够更新它。当然这只是一个假设的场景,完全不清楚这是否是您的情况以及是否需要保护这个 id

    【讨论】:

    • 嗨 Darin, id 值是从 Details(int id) 方法到 Edit(int id) 方法的资源 url 的一部分,当单击编辑视图上的保存按钮到 @987654325 时出现问题@ 方法。由于 Id 未绑定到 Edit 视图中的某些内容,因此它基本上从模型中消失了。您是否建议不要发送 ID 并保留该服务器端?我越想越倾向于更多地使用会话和WebSecurity 类提供的WebSecurity.GetUserId(User.Identity.Name) 方法。
    • @Jammer,正如我在回答中已经说过的那样,这取决于是否只允许当前经过身份验证的用户更新仅属于他的资源。如果有人可以编辑任何资源,您不必担心。如果只有资源所有者的用户可以编辑它,您仍然可以将 id 保留在隐藏字段中,但您绝对应该在服务器上执行所有权验证。
    【解决方案2】:

    如果 UserId 是敏感的,那么还有其他选项

    • 仅使用会话状态保留UserId 服务器端(如果您的架构允许Session
    • 将其放入encrypted cookie。请注意,根据 Darin,这些可以是 compromised

    如果它不敏感,那么您的HiddenFor 很好 - 将其与表单的其余部分一起发回。 不要把它放在你的 ActionLink 查询字符串中,除非这是你的路由的一部分(即 /Controller/Action/id)

    【讨论】:

    • 将敏感信息放入 cookie 是一种非常糟糕的方法,并不比将其放入隐藏字段或查询字符串参数更安全。
    【解决方案3】:

    我强烈建议使用 ValueInjecter。这是一个代码 sn-p 做同样的事情

    [HttpGet]
        public new ActionResult Profile()
        {
            var model = new ProfileModel();
    
            model.InjectFrom<UnflatLoopValueInjection>(this.GetCurrentUser());
    
            return View(model);
        }
    
        [HttpPost]
        public new ActionResult Profile(ProfileModel model)
        {
            if (ModelState.IsValid)
            {
                this.GetCurrentUser().InjectFrom<UnflatLoopValueInjection>(model);
    
                try
                {
                    _userService.SaveOrUpdate(this.GetCurrentUser());
                    TempData["Success"] = "User was successfully updated.";
                    return RedirectToAction("Profile");
                }
                catch (Exception)
                {
                    ModelState.AddModelError("Exception", "Unexpected error");
                }
            }
    
            return View(model);
        }
    

    这里是视图...

        @using (Html.BeginForm("Profile", "Account", FormMethod.Post, new { @class = "form-horizontal" }))
    {
        @Html.ValidationSummary(true, "Unable to update profile. Please correct the errors and try again.", new { @class = "alert alert-block alert-error" })
    
        @Html.EditorForModel()
    
        <div class="form-actions">
            <input type="submit" value="Update" class="btn btn-primary" />
        </div>        
    }
    

    【讨论】:

    • 我已经在使用 AutoMapper 从一个对象到另一个对象。我不确定您的答案针对的是什么问题。如果输入模型 id 为 0,它只会覆盖 IPrinciple 中的 id 值,不是吗?
    • 你在修改别人的资料吗?还是只是你自己的?如果我正在编辑自己的属性,则不需要视图模型中的 ID,因为我已经从原理中知道了这一点。
    猜你喜欢
    • 2012-06-18
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2011-04-27
    相关资源
    最近更新 更多