简体   繁体   English

回发后如何保持模型值而不暴露它们

[英]How to maintain model values after postback without exposing them

I'm working on a UserProfile edit page, where only a subset of the fields of a UserProfile model can be edited. 我正在处理UserProfile编辑页面,在该页面上只能编辑UserProfile模型字段的子集。 A number of fields are only editable for users with a special role, and the field UserName is of course uneditable and hidden. 只有具有特殊角色的用户才能编辑许多字段,而UserName字段当然是不可编辑和隐藏的。

Right now I'm thinking about including hiddenfields for all the fields that are not to be edited by users, and decorating my model like this: 现在,我正在考虑为所有用户不希望编辑的字段包括hiddenfields,并像这样装饰我的模型:

[Table("UserProfile")]
public partial class UserProfile
{
    public UserProfile()
    {
        webpages_Roles = new HashSet<Role>();
    }

    [Key]
    public int UserId { get; set; }

    [Required]
    [StringLength(56)]
    [Display(Name="Email")]
    [Editable(false)] // is this the way to go?
    public string UserName { get; set; }

    [Required]
    [Display(Name = "First name")]
    [StringLength(256)]
    public string FirstName { get; set; }

    [Editable(false)] // is this the way to go?
    public bool SomeSetting { get; set; }

    // ... more properties are unimportant for this example
}

Other related bits of code: 其他相关代码位:

    //
    // GET: /Account/Profile

    public ActionResult UserProfile()
    {
        var userProfile = db.UserProfiles.Find(WebSecurity.CurrentUserId);

        return View(userProfile);
    }

    //
    // POST: /Account/Profile

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult UserProfile(UserProfile model)
    {
        // if I dont include UserName, validation will fail since it 
        // is now null and the field is [Required]
        if (ModelState.IsValid)
        {
            // if I dont include hidden fields, UserId, UserName
            // and SomeSetting will be null here
            db.Entry(model).State = EntityState.Modified;
            db.SaveChanges();
        }

        return View(model);
    }

Related view code: 相关查看代码:

@Html.HiddenFor(m => m.UserId)
@Html.HiddenFor(m => m.UserName)
@Html.HiddenFor(m => m.SomeSetting)

However, I'm worried about exposing these fields through a hidden input. 但是,我担心要通过隐藏的输入来显示这些字段。 Won't clever or malicious users be able to edit them anyway? 聪明或恶意的用户仍然无法编辑它们吗? I understand that I HAVE to include them though, otherwise the properties will be null after postback. 我知道我必须将它们包括在内,否则回发后属性将为null Can someone enlighten me? 有人可以启发我吗?

You could do something like generate a hash as a property on your model which is the hash of all the values in a concatenated string - for example: 您可以执行一些操作,例如在模型上生成一个哈希值作为属性,它是串联字符串中所有值的哈希值,例如:

Add a new property to your ViewModel (you can use the [NotMapped] annotation if this is also your Database Object).: 将新属性添加到ViewModel中(如果这也是您的数据库对象,则可以使用[NotMapped]批注):

public string SecurityHash {get;set;}

Create a simple hashing function in a helper (or your controller): 在帮助程序(或您的控制器)中创建一个简单的哈希函数:

public string CalculateMD5Hash(string input)
{
    // step 1, calculate MD5 hash from input
    MD5 md5 = System.Security.Cryptography.MD5.Create();
    byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
    byte[] hash = md5.ComputeHash(inputBytes);

    // step 2, convert byte array to hex string
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < hash.Length; i++)
    {
        sb.Append(hash[i].ToString("X2"));
    }
    return sb.ToString();
}

Now set the hash value in your controller: 现在在您的控制器中设置哈希值:

//
// GET: /Account/Profile

public ActionResult UserProfile()
{
    var userProfile = db.UserProfiles.Find(WebSecurity.CurrentUserId);
    userProfile.SecurityHash = MyHashHelper.CalculateMD5Hash(userProfile.UserID + userProfile.UserName + userProfile.SomeSetting)
    return View(userProfile);
}

Then in your View, persist your hashed value: 然后在您的视图中,保留您的哈希值:

@Html.HiddenFor(m => m.UserId)
@Html.HiddenFor(m => m.UserName)
@Html.HiddenFor(m => m.SomeSetting)
@Html.HiddenFor(m => m.SecurityHash)

Then finally, you can check if your values have been tampered with buy re-hashing after the POST: 然后,最后,您可以检查POST之后是否对您的值进行了购买重新哈希处理的篡改:

//
// POST: /Account/Profile

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult UserProfile(UserProfile model)
{
    string hashCheckVal = MyHashHelper.CalculateMD5Hash(model.UserID + model.UserName + model.SomeSetting)
    if(string.Compare(hashCheckVal, model.SecurityHash) != 0)
    {
        throw new Exception("tampered with!");
    }

    // if I dont include UserName, validation will fail since it 
    // is now null and the field is [Required]
    if (ModelState.IsValid)
    {
        // if I dont include hidden fields, UserId, UserName
        // and SomeSetting will be null here
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }

    return View(model);
}

If you are concerned about security then you should retrieve your entity from the database after postback and then update the editable properties from the submitted model. 如果您担心安全性,那么应该在回发后从数据库中检索您的实体,然后从提交的模型中更新可编辑属性。 To retrieve your model I think it is ok to keep the UserId as a hidden field: @Html.HiddenFor(m => m.UserId) 要检索您的模型,我认为可以将UserId保留为隐藏字段: @Html.HiddenFor(m => m.UserId)

I hope this answer helps. 我希望这个答案会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM