MVC5 AntiForgeryToken-как обрабатывать "предоставленный токен защиты от подделки предназначен для пользователя", но текущий пользователь - "xxx".- исключение?

Я хочу защитить наши действия входа в систему с помощью AntiforgeryToken атрибут-я знаю, почему происходит исключение из темы, однако я не могу найти для него хорошего решения.

Допустим у нас есть следующие ситуации:

  1. это 8: 00 утра, пользователи приложений приходят на работу, они садятся и начинают процесс входа в систему-прямо сейчас это вполне возможно что некоторые из пользователей получат то же самое ValidationToken. После первого входа в систему-все остальные увидят вышеуказанное исключение (или другой пользовательский экран исключения) при попытке входа в систему.

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

таким образом, вопрос прост -как предотвратите вышеуказанные ситуации или как с ними обращаться, чтобы пользователи ничего не заметили. Я попробовал следующее:

  1. задание AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; на событий Application_Start в Global.асакс - это проблема, Я все еще получаю то же самое исключение
  2. задание [OutputCache (NoStore = true, Duration = 0, VaryByParam = "None")] о методе с [ValidateAntiForgeryToken] атрибут - опять же, не повезло там

прямо сейчас я думал вручную проверьте токен в теле действия, перехватить ошибку, и проверить, если попытка была сделана анонимным пользователем:

public ActionResult SomeAction()
{
    try
    {
        AntiForgery.Validate();
    }
    catch(HttpAntiForgeryException ex)
    {
        if(String.IsNullOrEmpty(HttpContext.User.Identity.Name))
        {
            throw;
        }
    }

    //Rest of action body here
    //..
    //..
}

выше, кажется, предотвращает ошибки -но безопасно ли это? какие существуют альтернативы?

спасибо заранее.

лучшие с уважением.

изменить:

окончательное "решение" состояло в том, чтобы отключить проверку токенов в форме входа в систему - может быть лучший способ справиться с этим, но кажется, что все решения, которые я нашел, были уродливыми обходными путями, подобными моим предложенным выше.

поскольку нет способа узнать, насколько "безопасны" эти альтернативы (если они вообще безопасны), мы решили отключить проверку токенов при входе в систему.

1 ответов


попробуйте установить (в глобальном.cs):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

это добавит идентификатор имени к вашему токену,

Что касается проблемы с двойным логином, попробуйте использовать скрипт для документирования даты и времени исходной отправки, чтобы остановить вторую отправку с тем же токеном.

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
  $(this).on('submit',function(e){
    var $form = $(this);

    if ($form.data('submitted') === true) {
      // Previously submitted - don't submit again
      e.preventDefault();
    } else {
      // Mark it so that the next submit can be ignored
      $form.data('submitted', true);
    }
  });

  // Keep chainability
  return this;
};

Итак, мы знаем одну вещь; пользователям нравится кнопка "назад" и привычка двойного щелчка, это большая проблема с AntiforgeryToken.

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

убедитесь, что форма сообщений об ошибках ясна и лаконична, чтобы обеспечить пользователь знает, что не так. Контекстные ошибки дают бонусные баллы.

всегда поддерживать состояние формы между представлениями формы. Не считая пароли или номера кредитных карт, нет оправдания благодаря В MVC формируйте помощников. @Html.LabelFor(x => x.FirstName)

если формы распределены между вкладками или скрытыми дивами, такими как используемые в Рамки СПА как угловое или Эмбер.js, будь умным и покажи макеты контроллера или форма, из которой на самом деле возникли ошибки отправка формы при отображении ошибки. Не просто направляйте их на главный контроллер или первую вкладку.

"что происходит?"- Информирование пользователя

когда AntiForgeryToken не проверяет ваш сайт будет выдавать исключение типа System.Сеть.В MVC.HttpAntiForgeryException.

если вы настроили правильно, у вас есть дружественные ошибки включены, и это будет означать, что ваша страница ошибок не покажет исключение и показать хорошую страницу ошибок, которая говорит им, что происходит.

вы можете сделать это немного проще, по крайней мере, предоставив пользователю более информативную страницу, ориентированную на эти исключения, поймав HttpAntiForgeryException.

private void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

    if (ex is HttpAntiForgeryException)
    {
        Response.Clear();
        Server.ClearError(); //make sure you log the exception first
        Response.Redirect("/error/antiforgery", true);
    }
}

и свой /error/antiforgery view может сказать им к сожалению вы пытались представить ту же информацию дважды

еще одна идея-зарегистрировать ошибку и вернуть пользователя на экран входа в систему:

создать HandleAntiforgeryTokenErrorAttribute класс, который переопределяет метод OnException.

HandleAntiforgeryTokenErrorAttribute.cs:

public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary(new { action = "Login", controller = "Account" }));
    }
}

Глобальный Фильтр:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new HandleAntiforgeryTokenErrorAttribute()
            { ExceptionType = typeof(HttpAntiForgeryException) }
        );
    }
}

Я бы также использовал несколько инструментов для запишите всю свою информацию, как логин является важной частью вашего приложения

NLog для общего ведения журнала и писем по критическим исключениям приложений (включая веб-исключения).

Elmah для фильтрации электронной почты и веб-исключений.

EDIT: Также вы можете посмотреть плагин jQuery под названием SafeForm. ссылке

EDIT:

Я видел много дебатов по этому поводу, и у всех взглядов на эту тему есть веские моменты, как я смотрю на это (взято из owasp.org)

Межсайтовая подделка запросов (CSRF) - это атака, которая заставляет конечного пользователя выполнение нежелательных действий в веб-приложении, в котором они в настоящее время аутентифицируется, CSRF атакует специально целевые запросы изменения состояния, а не кражу данные. Анти-подделки маркер для того, кто вошел'. Поэтому, как только вы войдете в систему, а затем вернетесь, старый токен больше не действителен

теперь я также использую авторизованные IP-адреса для входа в систему для выделения моих приложений с 2-факторной авторизацией, если IP-адрес пользователей изменяется, поэтому, если подделка межсайтового запроса была в игре, пользователь не будет соответствовать IP-адресу и запрашивать 2-факторную авторизацию. почти так же, как работает маршрутизатор безопасности. но если ты хочешь продолжать в том же духе ... ваша страница входа в систему я не вижу проблемы, пока у вас есть дружественные страницы ошибок, настроенные люди не расстроятся, поскольку они увидят, что они сделали что-то не так.