Кнопка "Назад" и токен анти-подделки
Я получаю Runtime error
связанный атрибут анти-подделки.
Выполните следующие шаги:
Ошибка: The provided anti-forgery token was meant for a different claims-based user than the current user.
Что можно сделать, чтобы предотвратить эту ошибку?
Ответы
Ответ 1
Это один из способов игнорировать ошибку и возвращать пользователя на экран входа в систему. Это просто пример.
Создайте новый класс с именем HandleAntiforgeryTokenErrorAttribute
, который наследуется от HandleErrorAttribute
. Переопределите метод OnException
.
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { action = "Login", controller = "Account" }));
}
}
Перейдите в свой FilterConfig
класс и зарегистрируйте атрибут как глобальный фильтр.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute()
{ ExceptionType = typeof(HttpAntiForgeryException) }
);
}
}
Ответ 2
У меня была такая же проблема только сейчас, и я решил ее отключить кэширование входа в систему. Это на самом деле имеет большой смысл и не требует обработки кода или исключений.
Теперь мой метод управления журналом выглядит следующим образом:
[AllowAnonymous]
[OutputCache(NoStore = true, Location = OutputCacheLocation.None)]
public ActionResult LogOn(Uri returnUrl)
Когда кеширование отключено, и пользователь нажимает кнопку "Назад" в браузере, на сервер добавляется новый запрос, и страница доставляется снова, а токен антикоррекции установлен на правильного пользователя.
Я считаю, что это намного более чистый, простой и логичный подход к проблеме.
Ответ 3
Кэшированные старые страницы, возвращенные к жизни с помощью кнопки "назад", содержат старые антиблокировочные жетоны и вызывают исключение. Решение глобального фильтра от Rowan Freeman перенаправляется на страницу входа в систему. Однако эта проблема кэширования также заставляет сайт обслуживать старую страницу входа со старым токеном. Отправка формы приведет к тому же исключению.
Ergo, IMO, должны быть реализованы оба решения (решения Rowan Freeman и julealgon).
Теоретически, избегая кэширования для каждой страницы, нужно также делать трюк, но при значительной стоимости (латентность, пропускная способность). Я выбираю перенаправить к логину, чтобы иметь возможность использовать кеширование и избегать кэширования при входе в систему для уменьшения исключения, т.е. Для реализации обоих.
Ответ 4
Принятые ответы просто улавливают все исключения, потому что они не фильтруют их по типу исключений, как это делает оригинальный HandleErrorAttribute.
Используйте следующий код, чтобы обрабатывать только HttpAntiForgeryException:
public static class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new HandleAntiforgeryTokenErrorAttribute());
}
}
public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
public HandleAntiforgeryTokenErrorAttribute()
{
ExceptionType = typeof(HttpAntiForgeryException);
}
public override void OnException(ExceptionContext filterContext)
{
if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
{
return;
}
filterContext.ExceptionHandled = true;
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(
new {
area = string.Empty,
action = "Index",
controller = "Home"
}));
}
}