Защита CSRF в Запросах Ajax с помощью MVC2

Страница, которую я создаю, зависит в большой степени от Ajax. В основном существует всего одна "страница", и каждая передача данных обрабатывается через Ajax. Так как сверхоптимистическое кэширование на стороне браузера приводит к странным проблемам (данные, не перезагруженные), я должен выполнить все запросы (также чтения) использование POST - который вызывает перезагрузку.

Теперь я хочу предотвратить страницу против CSRF. С представлением формы, с помощью Html.AntiForgeryToken() работы аккуратно, но в запросе AJAX, я предполагаю, что должен буду добавить маркер вручную? Есть ли что-нибудь out-of-the доступное поле?

Моя текущая попытка похожа на это:

Я хотел бы снова использовать существующее волшебство. Однако 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 который является частным, и я действительно не хотел копировать это, также.

В этой точке это, кажется, легче предложить решение собственной разработки, но это - действительно дублирующий код.

Какие-либо предложения, как сделать это умный путь? Я пропускаю что-то абсолютно очевидное?

8
задан Jon Seigel 3 April 2010 в 06:45
поделиться

1 ответ

Вы можете использовать обычный помощник 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>

, а затем выбрать соответствующий токен:

var token = $('#t1 input[name=__RequestVerificationToken]').val();
10
ответ дан 5 December 2019 в 17:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: