Устранение проблем с анти-подделкой

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

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

@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 not making it here
}

Вот машинаKey в файле 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();
}

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

Что еще может быть? Как устранить эту проблему?

Ответ 1

После помощи Адама, я получаю источник 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 с именем пользователя токена формы. В моем случае у меня не было набора имен пользователей (один был пустым, другой - пустой).

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

Ответ 2

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

Подождите...

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

Предоставленный токен анти-подделки предназначен для пользователя ", но текущий пользователь" [email protected]".

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

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

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

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

Ответ 3

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

$('#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'); 
});

Ответ 4

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

    < MachineKey validationKey = "DEBE0EEF2A779A4CAAC54EA51B9ACCDED506DA2A4BEBA88FA23AD8E7399C4A8B93A006ACC1D7FEAEE56A5571B5AB6D74819CFADB522FEEB101B4D0F97F4E91" decryptionKey = "7B1EF067E9C561EC2F4695578295EDD5EC454F0F61DBFDDADC2900B01A53D4" проверка = "SHA1" дешифрование = "АЕС" /" >

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

html error logger - неправильная строка.

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