Токен против подделки не может быть расшифрован

У меня есть форма:

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()
@Html.ValidationSummary()...

и действие:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl, string City)
{
}

изредка (раз в неделю) я получаю сообщение об ошибке:

Токен против подделки не может быть расшифрован. Если это приложение размещено на веб-ферме или в кластере, убедитесь, что на всех компьютерах установлена ​​одна и та же версия веб-страниц ASP.NET и что в конфигурации указаны явные ключи шифрования и проверки. Автогенерация не может использоваться в кластере.

я пытаюсь добавить в webconfig:

<machineKey validationKey="AutoGenerate,IsolateApps"  
    decryptionKey="AutoGenerate,IsolateApps" />

но ошибка все равно иногда появляется

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

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

14 ответов

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

validationKey="AutoGenerate"

Это заставляет ASP.NET генерировать новый ключ шифрования для использования при шифровании таких вещей, как аутентификационные билеты и токены защиты от подделки, при каждом запуске приложения. Если вы получили запрос, в котором использовался другой ключ (например, до перезапуска) для шифрования элементов запроса (например, файлов cookie аутентификации), это исключение может возникнуть.

Если вы отойдете от "Автогенерации" и конкретно укажете его (ключ шифрования), запросы, которые зависят от того ключа, будут правильно расшифрованы и проверка будет работать от перезапуска приложения до перезапуска. Например:

<machineKey  
validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
               AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"           
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"
/>

Вы можете прочитать на свой вкус на странице MSDN: Как: настроить MachineKey в ASP.NET

Просто генерировать <machineKey .../> пометить ссылку для вашей версии фреймворка и вставить в <system.web><system.web/> в Web.config, если он не существует.

Надеюсь это поможет.

Если вы пришли сюда из Google для своего компьютера разработчика с этой ошибкой, попробуйте очистить куки в браузере. У меня работали чистые куки браузера.

В asp.net Core необходимо установить систему защиты данных. Я тестирую в Asp.Net Core 2.1 или выше.

есть несколько способов сделать это, и вы можете найти дополнительную информацию в разделе Настройка защиты данных и замена ключа машины ASP.NET в ASP.NET Core и поставщиках хранилища ключей.

  • первый способ: локальный файл (простая реализация)

    Содержание startup.cs:

    public class Startup
    {
       public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
       {
           Configuration = configuration;
           WebHostEnvironment = webHostEnvironment;
       }
    
       public IConfiguration Configuration { get; }
       public IWebHostEnvironment WebHostEnvironment { get; }
    
       // This method gets called by the runtime.
       // Use this method to add services to the container.
       public void ConfigureServices(IServiceCollection services)
       {
           // .... Add your services like :
           // services.AddControllersWithViews();
           // services.AddRazorPages();
    
           // ----- finally Add this DataProtection -----
           var keysFolder = Path.Combine(WebHostEnvironment.ContentRootPath, "temp-keys");
           services.AddDataProtection()
               .SetApplicationName("Your_Project_Name")
               .PersistKeysToFileSystem(new DirectoryInfo(keysFolder))
               .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
       }
    }
    
  • второй способ: сохранить в БД

    В Microsoft.AspNetCore.DataProtection.EntityFrameworkCore Пакет NuGet необходимо добавить в файл проекта

    Добавить MyKeysConnection ConnectionString к вашим проектам ConnectionStrings в appsettings.json > ConnectionStrings > MyKeysConnection.

    Добавить MyKeysContext класс к вашему проекту.

    MyKeysContext.cs содержимое:

    public class MyKeysContext : DbContext, IDataProtectionKeyContext
    {
       // A recommended constructor overload when using EF Core 
       // with dependency injection.
       public MyKeysContext(DbContextOptions<MyKeysContext> options) 
           : base(options) { }
    
       // This maps to the table that stores keys.
       public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
    }
    

    Содержание startup.cs:

    public class Startup
    {
       public Startup(IConfiguration configuration)
       {
           Configuration = configuration;
       }
    
       public IConfiguration Configuration { get; }
    
       // This method gets called by the runtime.
       // Use this method to add services to the container.
       public void ConfigureServices(IServiceCollection services)
       {
           // ----- Add this DataProtection -----
           // Add a DbContext to store your Database Keys
           services.AddDbContext<MyKeysContext>(options =>
               options.UseSqlServer(Configuration.GetConnectionString("MyKeysConnection")));
    
           // using Microsoft.AspNetCore.DataProtection;
           services.AddDataProtection()
               .PersistKeysToDbContext<MyKeysContext>();
    
           // .... Add your services like :
           // services.AddControllersWithViews();
           // services.AddRazorPages();
       }
    }
    

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

Обновление: мне удалось это исправить, добавив следующие комментарии к моему входу:

https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/

Name    Description Values
nginx.ingress.kubernetes.io/affinity    Sets the affinity type  string (in NGINX only cookie is possible
nginx.ingress.kubernetes.io/session-cookie-name Name of the cookie that will be used    string (default to INGRESSCOOKIE)
nginx.ingress.kubernetes.io/session-cookie-hash Type of hash that will be used in cookie value  sha1/md5/index

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

Я изменился:

возврат View (индекс);

в

вернуть PartialView(index);

под моим контролем, и это решило мою проблему.

Я получил эту ошибку на.NET Core 2.1. Я исправил это, добавив сервис Data Protection в Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection();
    ....
}

Вы звоните более чем одному @Html.AntiForgeryToken() на ваш взгляд

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

Я нашел очень интересный способ решения этой проблемы, по крайней мере, в моем случае. Мое представление динамически загружало частичные представления с формами в div с использованием ajax, все в другой форме. основная форма не представляет проблем, и одна из частей работает, а другая - нет. ЕДИНСТВЕННАЯ разница между частичными представлениями заключалась в том, что в конце рабочего был пустой тег скрипта.

          <script type="text/javascript">
    </script> 

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

Для тех, кто получает эту ошибку в Google AppEngine или Google Cloud Run, вам необходимо настроить защиту данных вашего веб-сайта ASP.NET Core.

Документация от команды Google проста в использовании и работает.

Общий обзор документов Microsoft можно найти здесь:

https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_providerhttps://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider

Обратите внимание, что вы также можете обнаружить, что вам приходится входить в систему снова и снова, и происходят другие странные вещи. Это все потому, что Google Cloud не выполняет фиксированные сеансы, как это делает Azure, и вы фактически обращаетесь к разным экземплярам с каждым запросом.

Другие зарегистрированные ошибки включают:

      Identity.Application was not authenticated. Failure message: Unprotect ticket failed

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

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

У нас на глобальном уровне ключ машины был настроен на автоматическую генерацию из-за требований STIG.

Это раздражало, пока я не получил часть ответа здесь: /questions/11238226/kak-ustranit-isklyuchenie-antiforgerytoken-kotoroe-voznikaet-posle-iisreset-v-moem-prilozhenii-aspnet-mvc/11238261#11238261:

Если для вашего MachineKey установлено значение AutoGenerate, то ваши токены проверки и т. д. не переживут перезапуск приложения — ASP.NET сгенерирует новый ключ при запуске, а затем не сможет правильно расшифровать токены.

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

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

AntiForgery.GetTokens(null, out var cookieToken, out var formToken);
Другие вопросы по тегам