Asp.net

使用 MVC2 的 AJAX 請求中的 CSRF 保護

  • April 3, 2010

我正在建構的頁面很大程度上依賴於 AJAX。基本上,只有一個“頁面”,每個數據傳輸都通過 AJAX 處理。由於瀏覽器端過度樂觀的記憶體會導致奇怪的問題(數據未重新載入),因此我必須使用 POST 執行所有請求(也讀取) - 這會強制重新載入。

現在我想阻止頁面針對 CSRF。通過表單送出,使用Html.AntiForgeryToken()可以很好地工作,但是在 AJAX-request 中,我想我將不得不手動附加令牌?有什麼開箱即用的東西嗎?

我目前的嘗試如下所示

我很想重用現有的魔法。但是,HtmlHelper.GetAntiForgeryTokenAndSetCookie它是私有的,我不想在 MVC 中亂搞。另一種選擇是編寫一個擴展,如

public static string PlainAntiForgeryToken(this HtmlHelper helper)
{
   // extract the actual field value from the hidden input
   return helper.AntiForgeryToken().DoSomeHackyStringActions();
}

這有點 hacky 並留下更大的問題未解決:如何驗證該令牌?預設驗證實現是內部的,並且針對使用表單欄位進行了硬編碼。我試著寫一個稍微修改過的ValidateAntiForgeryTokenAttribute,但它使用的AntiForgeryDataSerializer是私有的,我也真的不想複製它。

在這一點上,提出一個本土解決方案似乎更容易,但這確實是重複的程式碼。

任何建議如何以聰明的方式做到這一點?我錯過了一些完全明顯的東西嗎?

您可以使用正常Html.AntiForgeryToken()幫助器在頁面某處(不一定在表單內)生成隱藏欄位,並將其包含在 ajax 請求中:

var token = $('input[name=__RequestVerificationToken]').val();
$.post(
   '/SomeAction', { '__RequestVerificationToken': token }, 
   function() {
       alert('Account Deleted.');
   }
);

要在伺服器端驗證它:

[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult SomeAction() 
{
   return View();
}

如果您的頁面上有多個標記,您可能需要指定要包含的標記。由於現有的助手生成具有相同名稱的隱藏欄位,因此很難製作一個好的選擇器,因此您可以將它們放在跨度內:

<span id="t1"><%= Html.AntiForgeryToken() %></span>
<span id="t2"><%= Html.AntiForgeryToken() %></span>

然後選擇對應的token:

var token = $('#t1 input[name=__RequestVerificationToken]').val();

引用自:https://stackoverflow.com/questions/2350102