【问题标题】:Need help to explain Readonly\ScaffoldColumn(false)需要帮助解释 Readonly\ScaffoldColumn(false)
【发布时间】:2012-03-31 17:11:47
【问题描述】:

请帮助解决这样的问题,不要严格判断,因为我是 MVC 的新手: 我有一个模型,用于在我的数据库中按 ID 存储用户名

public class Names
    {
public int NameId { get; set; }
public string Username { get; set; }
}

, 控制器

[HttpPost]
        public ActionResult EditforModel(Names Name)
        {
            if (ModelState.IsValid)
            {
                db.Entry(Name).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(Name);
        }

添加和编辑视图 添加效果很好,问题是关于编辑 我用

    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
        <fieldset>
        <legend> legend </legend>
        @Html.EditorForModel()
        <p>
                <input type="submit" value="Save" />
            </p>
    </fieldset>
    }

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

编辑我的模型。 当试图进入这个视图时,我看到了一个 ID 和用户名的编辑器,但是如果我填写 ID - 我有错误,因为在 DB 中没有具有此类 ID 的条目。 好的。让我们寻找隐藏编辑器的属性。 [ScaffoldColumn(false)] 类似于标记是否为 Id 呈现编辑器。 将它应用到我的模型中,我的视图中发布了“0”id。尝试另一个 attr。 [ReadOnly(true)] 使字段成为只读字段。但与此同时,我在发布 ID 时得到了“0”。 修改视图我为模型中的每个字段放置了一个编辑器

@Html.HiddenFor(model => model.NameId)
@Html.EditorFor(model => model.Username)

但使用它很危险,因为某些用户可能会通过 post-request 发布错误的 Id。

我不能使用 [ScaffoldColumn(false)] 在控制器的 [Httppost] 操作中应用 Id,通过在 DB 中搜索适当的用户条目,因为名称已更改.. 我不敢相信@Html.HiddenFor 是唯一的出路。但找不到一个:(

【问题讨论】:

  • 在隐藏的输入或动作方法参数中贴上id真的不危险。危险的是不验证当前用户实际上可以修改传递的 id。

标签: asp.net-mvc-3 http-post member-hiding


【解决方案1】:

正如您所提到的“[ScaffoldColumn(false)] 类似于标记是否为 Id 呈现编辑器”,并且 [ReadOnly(true)] 意味着该属性将在绑定时被默认模型绑定器排除你的模型。

问题在于 HTTP 协议是无状态协议,这意味着当用户将编辑表单发布到 MVC 控制器时,该控制器不知道他正在编辑哪个对象,除非你在你的对象中包含一些标识符从用户收到的请求,尽管由于您提到的原因(有人可以发布另一个 ID),包括真实的对象 ID 并不是一个好主意。

一种可能的解决方案是向视图发送带有加密 ID 的视图模型,并在控制器中解密此 ID。

对象的视图模型可能如下所示:

public class UserViewModel
{
    [HiddenInput(DisplayValue = false)]
    public string EncryptedId { get; set; }
    public string Username { get; set; }
}

所以你的 HttpGet 操作方法将是

    [HttpGet]
    public ActionResult EditforModel()
    {
        // fetching the real object "user"
        ...

        var userView = new UserViewModel
        {
            // passing the encrypted Id to the ViewModel object
            EncryptedId = new SimpleAES().EncryptToString(user.NameId.ToString()),
            Username = user.Username
        };

        // passing the ViewModel object to the View
        return View(userView);
    }

别忘了把你的 View 的模型改成 ViewModel

@model UserViewModel

现在 HttpPost 操作方法将接收 UserViewModel

    [HttpPost]
    public ActionResult EditforModel(UserViewModel Name)
    {
        if (ModelState.IsValid)
        {
            try
            {
                var strId = new SimpleAES().DecryptString(Name.EncryptedId);
                var id = int.Parse(strId);
                // select the real object using the decrypted Id
                var user = ...Single(p => p.NameId == id);
                // update the value from the ViewModel
                user.Username = Name.Username;
                db.Entry(user).State = EntityState.Modified;
            }
            catch (CryptographicException)
            {
                // handle the case where the encrypted key has been changed
                return View("Error");
            }

            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(Name);
    }

当用户尝试更改加密密钥时,解密将失败并抛出 CryptographicException,您可以在 catch 块中处理它。

您可以在此处找到 SimpleAES 加密类(不要忘记修复 Key 和 Vector 数组的值): Simple insecure two-way "obfuscation" for C#

PS: 该答案基于 Henry Mori 的以下答案: Asp.net MVC 3 Encrypt Hidden Values

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2017-02-07
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    相关资源
    最近更新 更多