状况:
我有一个模型并基于用户角色我想让用户只更新模型的某些部分。让我们说模型有三个字段。 (我的模型显然比这更复杂)
MyObject
Field1
Field2
Field3
My View看起来像这样:
Html.TextBoxFor(@Model.Field1)
Html.TextBoxFor(@Model.Field2)
@if(UserIsAdmin())
Html.TextBoxFor(@Model.Field3)
else
@Model.Field3
关于语法(以及示例的糟糕设计),我可以看到我正在尝试做什么。当用户发布表单时,我的控制器将只接受MyObject并将其保存回数据库,我们正在使用EF。
问题:
我的问题是,有没有办法阻止用户伪造POST以便能够保存他/她不应该能够的数据。我目前的想法是在控制器中检查用户是否修改了他不应该具有的值。或者我可以单独保存字段,但两者都不是一个方便的解决方案。
有更好的吗?
谢谢!
其他信息:
所有三个字段都来自同一个数据库表,我使用EF来获取和保存实体。
答案 0 :(得分:3)
您希望确保用户只能更新允许的字段。
您决定实现此目的的方法是阻止用户使用例如“伪造”响应。 firebug,或F12开发人员工具,或GreaseMonkey,并询问如何执行此操作。
但正确/最佳方法是检查用户尝试更新的字段,并仅更新允许更新的字段。然后,如果他们伪造请求并不重要,他们仍然无法访问他们不应该访问的任何内容。换句话说,检查访问点的访问权限。
防伪代币可以解决一个单独的问题,即XSRF。
答案 1 :(得分:2)
使用仅接受应更新的字段的viewmodel,然后使用这些值填充模型。您可以使用类似AutoMapper之类的内容来映射两者。
答案 2 :(得分:1)
我目前的想法是在控制器中检查以查看用户是否修改了他不应具有的值。或者我可以单独保存字段,但两者都不是一个方便的解决方案。
你的想法是正确的。典型的Add()
操作如下所示:
public class FooController : Controller
{
public ActionResult Add(FooViewModel viewModel)
{
if (ModelState.IsValid)
{
FooDataModel dataModel = FooMapper.MapToDataModel(viewModel, User);
FooRepository.Add(dataModel);
}
}
}
就像@VimalStan所说,你的FooViewModel
是一个只包含你想让用户更新的字段的模型。此外,这仍然无法解决您的问题,应该在您的映射器中完成(在本例中为FooMapper
)并仍然检查每个字段为@Ben建议:
public static class FooMapper
{
public static FooDataModel Map(FooViewModel viewModel, IPrincipal user)
{
var dataModel = new FooDataModel();
dataModel.Field1 = viewModel.Field1;
dataModel.Field2 = viewModel.Field2;
if (IsAllowedToUpdateField3(user))
{
dataModel.Field3 = viewModel.Field3;
}
return dataModel;
}
public static bool IsAllowedToUpdateField3(IPrincipal user)
{
return false; // your logic
}
}