我有点理解[ValidateAntiForgeryToken]
如何防止CSRF,并且已经通读this question,但是我不确定这是否可以防止有人伪造表单发布的参数。ItemList
具有一个Items
属性,该属性是项的集合,而User
属性是对其所属的ApplicationUser
的引用。 Item
具有ItemList
属性,该属性是对其所属列表的引用。这是ItemController中的Add方法:
// GET: Item/Add/4 (Adds new Item to the ItemList with ID=4)
public ActionResult Add(int? itemListId)
{
// Gets the current user and the ItemList that the Item will be added to
UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
ApplicationUser currentUser = userManager.FindById(User.Identity.GetUserId());
ItemList itemList = db.ItemLists.Find(itemListId);
// Makes sure that ItemList exists and belongs to the user
if (itemList == null || itemList.User != currentUser)
{
return View("InsufficientPerm");
}
ViewBag.ItemListId = itemListId;
return View();
}
// POST: Item/Add/4 (Adds new Item to the ItemList with ID=4)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Add([Bind(Include = "ID,Name")] Item item, int? itemListId)
{
if (ModelState.IsValid)
{
ItemList itemList = db.ItemLists.Find(itemListId);
item.ItemList = itemList;
db.Items.Add(item);
itemList.Items.Add(item);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(item);
}
我的问题是
[ValidateAntiForgeryToken]
是否可以防止用户在发布期间伪造itemListId
参数,或者是否需要在post方法中放置另一个if (itemList == null...
检查。编辑:这是我现在正在查看的逻辑:
ValidateAntiForgeryToken
的使用迫使用户访问第一种方法(因此加载视图),以便接受帖子。如果他们没有加载该视图,那么将不会有防伪令牌。用户将转到表单网页(假设
http://foo.bar/Item/Add/3
)用户将填写并提交表单,该表单将调用post方法(在本例中为
itemListId=3
,因为这是所访问的网页)用户无法将不同的itemListId传递到上述步骤,因为网页在提交表单时会通过它传递
现在,请让我知道我上面所说的内容是否有问题,或者该逻辑是否正确(这意味着我无需在发布过程中检查itemListId的有效性)。请举一个例子或链接来阐明我的逻辑不正确之处
最佳答案
用户无法将不同的itemListId传递到上述步骤,因为网页在提交表单时会通过它传递
这是错误的。 AntiForgeryToken不会保护您免受数据更改的影响。
向Item/Add/4
发出GET请求。我假设您将在此页面上有一个表格。您可以包含@Html.AntiForgeryToken()
。
使用浏览器的调试工具检查表单。
现在,您可以编辑action
属性以直接修改Item/Add/5
值。
或修改任何<input>
字段值。
在POST操作上放置调试中断,然后在提交表单时会看到更改的值。
以上不是篡改数据的唯一方法。因此,您应始终验证任何输入。
[Authorize, ValidateAntiForgeryToken]
[HttpPost]
public ActionResult NukeMyBankAccount(int accountId)
{
var account = db.GetAccount(accountId);
// validate
if (CurrentUser.Id != account.Owner.Id)
{
return RedirectToAction("Unauthorized");
}
else
{
db.NukeAccount(accountId, areYouSure: true);
}
...
}