【发布时间】:2018-01-10 17:13:41
【问题描述】:
寻找一种干净、安全的方式,只允许某些用户(按角色)编辑视图中的某些字段。这里的关键词是edit,因为只显示/隐藏视图的一部分(按钮、链接等)是一回事,而如何处理“受保护”字段则是另一回事被发布回控制器。
例如,我可以这样做:
查看模型
public class CustomerEditViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
// Other properties...
public string Email { get; set; }
public string Phone { get; set; }
public bool CanEditContactInfo { get; set; }
}
查看
@Html.EditorFor(m => m.FirstName)
@Html.EditorFor(m => m.LastName)
@if (Model.CanEditContactInfo)
{
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.Phone)
}
控制器
[HttpGet]
public ActionResult Edit(int id)
{
var customer = _customerService.GetCustomerById(id);
var model = Mapper.Map<CustomerEditViewModel>(customer);
model.CanEditContactInfo = User.IsInRole("Admin");
return View(model);
}
[HttpPost]
public ActionResult Edit(CustomerEditViewModel model)
{
var customer = _customerRepo.GetCustomerById(model.Id);
Mapper.Map(model, customer);
_customerService.UpdateCustomer(customer);
// return to Index view
}
但问题是,当非管理员用户编辑客户时,Email 和 Phone 字段永远不会在视图上呈现,因此当表单回发到控制器时它们将为 NULL,并且会进一步用 NULL 覆盖数据库中的实际值。
我可以这样解决:
@Html.EditorFor(m => m.FirstName)
@Html.EditorFor(m => m.LastName)
@if (Model.CanEditContactInfo)
{
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.Phone)
}
else
{
@Html.HiddenFor(m => m.Email)
@Html.HiddenFor(m => m.Phone)
}
即使非管理员用户正在编辑记录,这也会保留原始电子邮件/电话值,但问题是电子邮件/电话字段在呈现的 HTML 中作为隐藏字段可用,并且可以很容易地被发回之前的浏览器工具。
我确实有一些想法,但它们变得一团糟。所以我想知道对于这样的事情可能已经有哪些成功的方法。
【问题讨论】:
-
如果用户没有角色,为什么不直接忽略这些字段?
-
取决于您所说的“忽略”。我已经解释过,如果只是从视图中忽略(即“忽略它们”的一种方式),它们在回发到控制器时将为 NULL,并将这些 NULL 保存到数据库中(覆盖实际的电子邮件/电话值)。除非您所说的“忽略”是指别的意思?
-
我的意思是无论你在哪里更新实体数据都忽略它们(我猜是
UpdateCustomer) -
我明白了。我认为这是有道理的,但我必须将用户的角色下推到该层(我的“服务”层),以便它可以检查进行更新的人是否是管理员。或者,我可以进行两个单独的服务调用,例如
UpdateCustomer和UpdateCustomerWithContactInfo,但不确定这是否正确。 -
在我看来,您的服务层应该已经强制执行此类权利/权限。
标签: c# asp.net-mvc security razor security-trimming