Правильная обработка бесформенных AJAX POST и AntiForgery в C# Razor PagesC#

Место общения программистов C#
Ответить
Anonymous
 Правильная обработка бесформенных AJAX POST и AntiForgery в C# Razor Pages

Сообщение Anonymous »

В этом гипотетическом сценарии я показываю список сообщений на странице.
Фрагмент JavaScript — Edit(id) — извлекает с сервера правильный HTML для редактирования сообщения и встраивает его на страницу.
Другой фрагмент javascript — Save(id) — отправляет AJAX POST обратно на сервер и вставляет результат. обратно на страницу.
Согласно правилам AntiForgery Razor Pages, POST вызывает ошибку 404, поскольку отсутствует правильный токен. Поскольку я не использую , встроенная система защиты от подделки не срабатывает автоматически и не предоставляет токен.
И поскольку у меня есть такая возможность Теоретически параллельно редактируя несколько сообщений, я не уверен, как правильно реализовать поле @Html.AntiForgeryToken(). Должен ли я генерировать токен для каждого сообщения, а затем каким-то образом собирать его и отправлять вместе с моим POST, или...?
Мне интересно, есть ли правильный способ обработки этот сценарий, который учитывает AntiForgery, или мне просто придется смириться с этим и строить вокруг него? Я могу легко обойти эту проблему с помощью [IgnoreAntiforgeryToken], но это, очевидно, имеет свои последствия.
На данный момент MessageManager.Messages — это всего лишь статический список

View.cshtml

Код: Выделить всё

@foreach (var item in Model.Messages) {

@item.Type:
@{
var result = Markdown.ToHtml(item.Message, pipeline);
@Html.Raw(result)
}

[url=#]✏[/url]
[url=#]❌[/url]

}

@section Scripts {

function Edit(messageId) {
$.get(
"/Messages/_EditMessage?messageId=" + messageId,
function (str) {
$('#message_' + messageId).html(str);
}
);
}
function Save(messageId) {
$.post(
"/Messages/_EditMessage?messageId=" + messageId,
{ NewMessage: $('#NewMessage_' + messageId).val() },
function (str) {
$('#message_' + messageId).html(str);
}
);
}

}

_EditMessage.cshtml

Код: Выделить всё

@if (Model.Edit) {

@Model.Message.Type
@Model.Message.Message

Save

}
else {
var result = Markdown.ToHtml(Model.Message.Message, pipeline);

@Model.Message.Type:
@Html.Raw(result)
}

_EditMessage.cshtml.cs

Код: Выделить всё

[IgnoreAntiforgeryToken]
public class _EditMessageModel : PageModel
{
public TextMessage Message { get; set; } = null!;
public bool Edit { get; set; }

[BindProperty] public string NewMessage { get; set; } = string.Empty;

public IActionResult OnGet(int messageId) {
var message = MessageManager.Messages.FirstOrDefault(m => m.Id == messageId);
if (message is null)
return NotFound(messageId);

Message = message;
Edit = true;

return Page();
}

public IActionResult OnPost(int messageId) {
var message = MessageManager.Messages.FirstOrDefault(m => m.Id == messageId);
if (message is null)
return NotFound(messageId);

Message = message;
Message.Message = NewMessage;
Edit = false;

return Page();
}
}
Вывод
Все действительно было так просто.
Добавьте @ Html.AntiForgeryToken() в нижнюю часть страницы просмотра и замените функцию Save() на

Код: Выделить всё

function Save(messageId) {
$.ajax({
type: "POST",
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
url: "/Messages/_EditMessage?messageId=" + messageId,
data: { NewMessage: $('#NewMessage_' + messageId).val() }
}).done(function(response){
$('#message_' + messageId).html(response);
});
}
Похоже, он не жалуется на повторное использование одного и того же токена для отправки нескольких POST.


Подробнее здесь: https://stackoverflow.com/questions/789 ... azor-pages
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»