我有点理解[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);
    }
    ...
}

09-11 17:46