Я реализовал в своем приложении защиту от CSRF-атак, следуя информации, которую я прочитал в блоге в Интернете. В частности, этот пост был драйвером моей реализации
- Рекомендации для ASP.NET MVC от команды разработчиков контента для ASP.NET и веб-инструментов
- Анатомия мошенничества с межсайтовым запросом Атака из блога Фила Хаака
- AntiForgeryToken в ASP.NET MVC Framework - атрибут Html.AntiForgeryToken и ValidateAntiForgeryToken из блога Дэвида Хейдена
В основном в этих статьях и рекомендациях говорится, что для предотвращения атаки CSRF любой должен реализовать следующий код:
1) Добавьте [ValidateAntiForgeryToken]
на каждое действие, которое принимает глагол POST Http
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}
2) Добавьте <%= Html.AntiForgeryToken() %>
помощника внутри формы, которая передает данные на сервер
<div style="text-align:right; padding: 8px;">
<%= Html.AntiForgeryToken() %>
<input type="submit" id="btnSave" value="Save" />
</div>
Во всяком случае, в некоторых частях моего приложения я выполняю POST Ajax с jQuery на сервере, не имея никакой формы. Это происходит, например, когда я позволяю пользователю нажимать на изображение для выполнения определенного действия.
Предположим, у меня есть таблица со списком мероприятий. У меня есть изображение в столбце таблицы с надписью «Пометить активность как выполненную», и когда пользователь нажимает на эту активность, я выполняю Ajax POST, как в следующем примере:
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {},
success: function (response) {
// ....
}
});
});
Как я могу использовать <%= Html.AntiForgeryToken() %>
в этих случаях? Должен ли я включить вспомогательный вызов в параметр данных вызова Ajax?
Извините за длинный пост и большое спасибо за помощь
РЕДАКТИРОВАТЬ :
Согласно jayrdub ответа я использовал следующий образ
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {
AddAntiForgeryToken({}),
id: parseInt($(this).attr("title"))
},
success: function (response) {
// ....
}
});
});
Ответы:
Я использую простую функцию JS, как это
Поскольку каждая форма на странице будет иметь одинаковое значение для токена, просто поместите что-то вроде этого на свою самую верхнюю главную страницу
Затем в вашем вызове ajax do (отредактировано в соответствии с вашим вторым примером)
источник
AddAntiForgeryToken
, вот так:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
ajaxSend
или переопределить,ajax
чтобы всегда дополнятьdata
токеном против подделки? Может быть, добавив некоторые проверки, чтобы убедиться, чтоurl
предназначен для вашего сервера.Мне нравится решение, предоставляемое 360Airwalk, но оно может быть немного улучшено.
Первая проблема заключается в том, что если вы делаете
$.post()
с пустыми данными, jQuery не добавляетContent-Type
заголовок, и в этом случае ASP.NET MVC не может получить и проверить токен. Таким образом, вы должны убедиться, что заголовок всегда там.Другим улучшением является поддержка всех HTTP-глаголов с содержимым : POST, PUT, DELETE и т. Д. Хотя вы можете использовать только POST в своем приложении, лучше иметь общее решение и убедиться, что все данные, которые вы получаете с любым глаголом, имеют защиту от подделки. маркер.
источник
.ajaxSend()
состояний «Начиная с jQuery 1.8, метод .ajaxSend () должен быть прикреплен только к документу». api.jquery.com/ajaxsendoptions
, что указано в окончательномif
утверждении? Спасибо.Я знаю, что есть много других ответов, но эта статья хороша и лаконична и заставляет вас проверять все ваши HttpPosts, а не только некоторые из них:
http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/
Он использует заголовки HTTP вместо попытки изменить коллекцию форм.
сервер
клиент
источник
Я чувствую себя продвинутым некромантом здесь, но это все еще проблема 4 года спустя в MVC5.
Для правильной обработки ajax-запросов токен защиты от подделки должен передаваться на сервер при ajax-вызовах. Интеграция его в ваши почтовые данные и модели является грязной и ненужной. Добавление токена в качестве пользовательского заголовка является чистым и пригодным для повторного использования - и вы можете настроить его так, чтобы вам не приходилось делать это каждый раз.
Есть исключение - ненавязчивый ajax не требует специальной обработки для вызовов ajax. Маркер передается как обычно в обычном скрытом поле ввода. Точно так же, как обычный пост.
_Layout.cshtml
В _layout.cshtml у меня есть этот блок JavaScript. Он не записывает токен в DOM, а использует jQuery для извлечения его из скрытого входного литерала, который генерирует помощник MVC. Волшебная строка, которая является именем заголовка, определяется как константа в классе атрибута.
Обратите внимание на использование одинарных кавычек в функции beforeSend - в отображаемом элементе ввода используются двойные кавычки, которые разбивают литерал JavaScript.
Клиентский JavaScript
Когда это выполняется, вызывается указанная выше функция beforeSend, и AntiForgeryToken автоматически добавляется в заголовки запроса.
Серверная библиотека
Пользовательский атрибут необходим для обработки нестандартного токена. Это основано на решении @ viggity, но правильно обрабатывает ненавязчивый Ajax. Этот код можно спрятать в вашей общей библиотеке
Сервер / Контроллер
Теперь вы просто применяете атрибут к своему действию. Еще лучше, вы можете применить атрибут к контроллеру, и все запросы будут проверены.
источник
$.ajaxSetup
определение общегоbeforesend
обработчика событий, может случиться так, что вы перезапишете его. Я нашел другое решение, где вы можете добавить второй обработчик, который также будет вызываться. Работает хорошо и не нарушает вашу реализацию.Не используйте Html.AntiForgeryToken . Вместо этого используйте AntiForgery.GetTokens и AntiForgery.Validate из Web API, как описано в разделе Предотвращение атак подделки межсайтовых запросов (CSRF) в приложении ASP.NET MVC .
источник
Я только что реализовал эту актуальную проблему в моем текущем проекте. Я сделал это для всех ajax-POST, которые нуждались в аутентифицированном пользователе.
Во-первых, я решил перехватить мои jjery ajax-звонки, чтобы не повторяться слишком часто. этот фрагмент javascript гарантирует, что все вызовы ajax (post) добавят в запрос маркер проверки моего запроса. Примечание: имя __RequestVerificationToken используется платформой .Net, поэтому я могу использовать стандартные функции Anti-CSRF, как показано ниже.
В ваших представлениях, где вам нужно, чтобы токен был доступен для вышеуказанного javascript, просто используйте общий HTML-помощник. Вы можете добавить этот код везде, где хотите. Я поместил его в оператор if (Request.IsAuthenticated):
В вашем контроллере просто используйте стандартный механизм ASP.Net MVC Anti-CSRF. Я сделал это так (хотя я на самом деле использовал соль).
С помощью Firebug или аналогичного инструмента вы можете легко увидеть, как к вашим запросам POST теперь добавлен параметр __RequestVerificationToken.
источник
Я думаю, все, что вам нужно сделать, это убедиться, что вход «__RequestVerificationToken» включен в запрос POST. Другая половина информации (то есть токен в файле cookie пользователя) уже автоматически отправляется с запросом AJAX POST.
Например,
источник
AntiForgeryToken
это все равно будет спорным. Если это так (не уверен, как вы получаете один в этом случае, но при условии, что вы), то вышеописанное будет работать просто отлично. Если вы пытаетесь создать простую веб-страницу, которая отправит запрос на сервер, ожидающий указанный токен, и сервер не сгенерировал указанную страницу, то вам не повезло. В этом и заключается смысл AntiForgeryToken ...Вы можете сделать это также:
Это использует
Razor
, но если вы используетеWebForms
синтаксис, вы можете также использовать<%= %>
тегиисточник
В дополнение к моему комментарию против ответа @ JBall, который помог мне на этом пути, это последний ответ, который работает для меня. Я использую MVC и Razor и отправляю форму с использованием jQuery AJAX, чтобы я мог обновить частичное представление с некоторыми новыми результатами, и я не хотел делать полный постбэк (и мерцание страницы).
Добавьте
@Html.AntiForgeryToken()
внутри форму как обычно.Мой код кнопки отправки AJAX (то есть событие onclick):
Я оставил действие "success", так как оно показывает, как обновляется частичное представление, содержащее MvcJqGrid и как оно обновляется (очень мощная сетка jqGrid, и это блестящая оболочка MVC для нее).
Мой метод контроллера выглядит так:
Я должен признать, что не являюсь поклонником размещения данных всей формы как модели, но если вам нужно сделать это, то это один из способов, который работает. MVC просто делает привязку данных слишком легкой, поэтому вместо подстановки 16 отдельных значений (или слабо типизированной формы FormCollection) это нормально, я полагаю. Если вы знаете лучше, пожалуйста, дайте мне знать, так как я хочу создать надежный код MVC C #.
источник
нашел эту очень умную идею из https://gist.github.com/scottrippey/3428114 для каждого вызова $ .ajax, он изменяет запрос и добавляет токен.
источник
if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {
чтобы перехватывать вызовы Ajax, которые не указали тип содержимого1. Определить функцию для получения токена с сервера
2. Получить токен и установить заголовок перед отправкой на сервер
3. Проверка сервера на HttpRequestBase для метода, который вы обрабатываете Post / get
источник
Я знаю, что прошло некоторое время с тех пор, как этот вопрос был опубликован, но я нашел действительно полезный ресурс, который обсуждает использование AntiForgeryToken и делает его менее трудным для использования. Он также предоставляет плагин jquery для простого включения токена защиты от подделки в вызовы AJAX:
Рецепты против подделки запроса для ASP.NET MVC и AJAX
Я не очень помогаю, но, возможно, кто-то найдет это полезным.
источник
источник
Вот самый простой способ, который я видел. Примечание. Убедитесь, что у вас в представлении «@ Html.AntiForgeryToken ()»
источник
Небольшое улучшение для решения 360Airwalk. Это вставляет токен Anti Forgery в функцию javascript, поэтому @ Html.AntiForgeryToken () больше не нужно включать в каждое представление.
источник
источник
Я использую сообщение ajax для запуска метода удаления (происходит из временной шкалы visjs, но это не очень важно). Это то, что я сестренка:
Это мой Index.cshtml
Все, что я добавил здесь, это
@Html.AntiForgeryToken()
чтобы токен появился на странице.Тогда в своем посте ajax я использовал:
Который добавляет значение токена, удаленное со страницы, к опубликованным полям
До этого я пытался поместить значение в заголовки, но я получил ту же ошибку
Не стесняйтесь размещать улучшения. Это, конечно, кажется простым подходом, который я могу понять
источник
Хорошо, здесь много постов, ни одно из них не помогло мне, дни и дни Google, и до сих пор я больше не дошел до того, что написал все приложение с нуля, а потом заметил этот маленький самородок в моем Web.confg.
Теперь я не знаю, почему я добавил его, однако с тех пор заметил, что он игнорируется в режиме отладки, а не в рабочем режиме (IE установлен в IIS Somewhere)
Для меня решение было одним из 2 вариантов, так как я не помню, почему я добавил его, я не могу быть уверен, что другие вещи не зависят от него, и во-вторых, доменное имя должно быть все в нижнем регистре и TLD не так, как я сделал в * .localLookup.net
Может быть, это помогает, может быть, нет. Я надеюсь, что это поможет кому-то
источник
Решение, которое я нашел, предназначено не для ASPX, а для Razor, но вполне решаемой проблемой.
Я решил это, добавив AntiForgery к запросу. Помощник HTML не создает идентификатор HTML с вызовом
Чтобы добавить токен в пост-запрос, я просто добавил идентификатор AntiForgery в скрытое поле с помощью jquery:
Это заставило контроллер принять запрос с атрибутом [ValidateAntiForgeryToken]
источник
AntiforgeryToken - все еще боль, ни один из примеров выше не работал слово в слово для меня. Слишком много для там. Поэтому я объединил их всех. Нужен @ Html.AntiforgeryToken в форме, висящей вокруг iirc
Решено так:
Если сомневаетесь, добавьте больше знаков $
источник