Устранение проблем с фальсификацией токенов - PullRequest
34 голосов
/ 24 апреля 2011

У меня есть сообщение в форме, в котором постоянно выдается ошибка с токеном против подделки.

Вот моя форма:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.EditorFor(m => m.Email)
    @Html.EditorFor(m => m.Birthday)
    <p>
        <input type="submit" id="Go" value="Go" />
    </p>
}

Вот мой метод действия:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Join(JoinViewModel model)
{
    //a bunch of stuff here but it doesn't matter because it's not making it here
}

Вот ключ машины в web.config:

<system.web>
  <machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>

И вот ошибка, которую я получаю:

A required anti-forgery token was not supplied or was invalid.

Я читал, что изменение пользователей в HttpContext приведет к аннулированию токена, но здесь этого не происходит. HttpGet в моем действии Join просто возвращает представление:

[HttpGet]
public ActionResult Join()
{
    return this.View();
}

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

Что еще может происходить? Как я могу устранить это?

Ответы [ 11 ]

31 голосов
/ 24 февраля 2013

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

Жди ...

  • Убедитесь, что вы вышли из системы, затем введите свой логин
  • Двойной щелчок по кнопке входа
  • Вы получите:

Предоставленный токен защиты от подделки был предназначен для пользователя "", но текущий пользователь - "XXX@yahoo.com".

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

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

Я только что удалил атрибут проверки. Мой сайт всегда SSL, и я не слишком обеспокоен риском. Мне просто нужно, чтобы это работало прямо сейчас. Другим решением было бы отключить кнопку с помощью JavaScript.

Это может быть продублировано в шаблоне начальной установки MVC4.

19 голосов
/ 25 апреля 2011

После помощи Адама я добавил источник MVC в свой проект и смог увидеть, что во многих случаях возникает одна и та же ошибка.

Вот метод, используемый для проверки токена защиты от подделки:

    public void Validate(HttpContextBase context, string salt) {
        Debug.Assert(context != null);

        string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
        string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);

        HttpCookie cookie = context.Request.Cookies[cookieName];
        if (cookie == null || String.IsNullOrEmpty(cookie.Value)) {
            // error: cookie token is missing
            throw CreateValidationException();
        }
        AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);

        string formValue = context.Request.Form[fieldName];
        if (String.IsNullOrEmpty(formValue)) {
            // error: form token is missing
            throw CreateValidationException();
        }
        AntiForgeryData formToken = Serializer.Deserialize(formValue);

        if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
            // error: form token does not match cookie token
            throw CreateValidationException();
        }

        string currentUsername = AntiForgeryData.GetUsername(context.User);
        if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
            // error: form token is not valid for this user
            // (don't care about cookie token)
            throw CreateValidationException();
        }

        if (!String.Equals(salt ?? String.Empty, formToken.Salt, StringComparison.Ordinal)) {
            // error: custom validation failed
            throw CreateValidationException();
        }
    }

Моя проблема заключалась в том, что он сравнивает имя пользователя Identity с именем пользователя токена формы. В моем случае у меня не было задано имя пользователя (одно было пустым, другое пустым).

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

9 голосов
/ 10 февраля 2014

AntiForgeryToken также проверяет, не изменились ли ваши авторизованные учетные данные пользователя - они также зашифрованы в файле cookie. Вы можете отключить это, установив AntiForgeryConfig.SuppressIdentityHeuristicChecks = true в файле global.asax.cs.

8 голосов
/ 19 июня 2014

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

$('#loginForm').on('submit',function(e){
    var $form = $(this);

    if (!$form.data('submitted') && $form.valid()) {
      // mark it so that the next submit can be ignored
      $form.data('submitted', true);
      return;
    }

    // form is invalid or previously submitted - skip submit
    e.preventDefault();
});

или

$('#loginForm').submit(function () {
    $(this).find(':submit').attr('disabled', 'disabled'); 
});
3 голосов
/ 14 декабря 2012

Я только что столкнулся с проблемой, когда @Html.AntiForgeryToken() вызывался дважды, поэтому токен Anti-Forger был испорчен в полезной нагрузке HTTP Post.

2 голосов
/ 02 октября 2015

Необходимо проверить правильность формы, прежде чем отключить кнопку отправки.

<script type="text/javascript">
//prevent double form submission
$('form', '#loginForm').submit(function () {
    if ($(this).valid()) {
        $(this).find(':submit').attr('disabled', 'disabled');
    }
});

2 голосов
/ 24 апреля 2011

Вы на одном сервере или веб-ферме?Если это один сервер, закомментируйте элемент machineKey в файле web.config и попробуйте снова в качестве базовой отправной точки.Любое изменение?Кроме того - можете ли вы подумать о каких-либо причинах, по которым ваши куки-файлы будут очищены или срок их действия истечет, - они также необходимы для правильной работы.

1 голос
/ 01 июня 2018

У меня просто была похожая проблема.Я получил:

The required anti-forgery form field "__RequestVerificationToken" is not present. 

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

var formField = HttpContext.Request.Params["__RequestVerificationToken"];
var cookie = System.Web.HttpContext.Current.Request.Cookies["__RequestVerificationToken"].Value;

На самом деле я должен был иметьЯ искал здесь:

var formField = HttpContext.Request.Form["__RequestVerificationToken"];

Так как Params содержит больше, чем просто поля формы, он содержит QueryString, Form, Cookies и ServerVariables.

Как только эта красная сельдь исчезла, яобнаружил, что AntiForgeryToken был в неправильной форме!

1 голос
/ 22 апреля 2016

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

  1. ASP.NET автоматически создает ключ криптографии для каждого приложения и сохраняет ключ в кусте реестра HKCU.При переносе или обращении к приложению на ферме серверов эти ключи не совпадают, поэтому первый способ заключается в добавлении уникального ключа компьютера в файл web.config.Ключ компьютера можно сгенерировать из консоли управления IIS и добавить в раздел вашего web.config

  2. Второй метод - предоставить доступ к реестру HKCU для рабочего процесса через appPool с помощью AspNet_RegIIS и ключ -ga или для всех приложений, использующих -i

aspnet_regiis -ga "IIS APPPOOL \ app-pool-name"

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

1 голос
/ 01 ноября 2014

Еще одна возможная вещь для проверки, которая вызвала у меня эту ошибку: у меня было два @Html.AntiForgeryToken() в одной из моих форм.

Как только проблема была устранена, проблема исчезла.

...