如何在回发后维护模型值而不公开它们
本文关键字:模型 维护 | 更新日期: 2023-09-27 18:20:58
我正在使用UserProfile编辑页面,在该页面上只能编辑UserProfile模型的字段子集。许多字段仅对具有特殊角色的用户可编辑,字段UserName当然是不可编辑和隐藏的。
现在我正在考虑为所有不需要用户编辑的字段添加隐藏字段,并将我的模型装饰成这样:
[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
}
其他相关代码位:
//
// 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);
}
相关视图代码:
@Html.HiddenFor(m => m.UserId)
@Html.HiddenFor(m => m.UserName)
@Html.HiddenFor(m => m.SomeSetting)
但是,我担心通过隐藏的输入暴露这些字段。聪明或恶意的用户无论如何都不能编辑它们吗?我知道我必须包括它们,否则回发后属性将为null
。有人能启发我吗?
您可以在模型上生成一个散列作为属性,该属性是串联字符串中所有值的散列,例如:
将新属性添加到ViewModel中(如果这也是数据库对象,则可以使用[NotMapped]注释)
public string SecurityHash {get;set;}
在助手(或控制器)中创建一个简单的哈希函数:
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();
}
现在在控制器中设置哈希值:
//
// 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);
}
然后在你的视图中,保持你的哈希值:
@Html.HiddenFor(m => m.UserId)
@Html.HiddenFor(m => m.UserName)
@Html.HiddenFor(m => m.SomeSetting)
@Html.HiddenFor(m => m.SecurityHash)
最后,您可以检查您的值是否被篡改,并在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);
}
如果您关心安全性,则应在回发后从数据库中检索实体,然后从提交的模型中更新可编辑属性。为了检索您的模型,我认为可以将UserId保留为隐藏字段:@Html.HiddenFor(m => m.UserId)
我希望这个答案能有所帮助。