asp.net-mvc 无法解密防伪令牌

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23402210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 03:40:05  来源:igfitidea点击:

The anti-forgery token could not be decrypted

asp.net-mvcasp.net-mvc-4

提问by user3331122

I have a form:

我有一个表格:

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

and action:

和行动:

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

occasionally (once a week), I get the error:

偶尔(每周一次),我收到错误消息:

The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.

无法解密防伪令牌。如果此应用程序由 Web 场或群集托管,请确保所有计算机都运行相同版本的 ASP.NET 网页,并且配置指定显式​​加密和验证密钥。AutoGenerate 不能在集群中使用。

i try add to webconfig:

我尝试添加到 webconfig:

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

but the error still appears occasionally

但错误仍然偶尔出现

I noticed this error occurs, for example when a person came from one computer and then trying another computer

我注意到会发生此错误,例如当一个人来自一台计算机然后尝试另一台计算机时

Or sometimes an auto value set with incorrect data type like bool to integer to the form field by any jQuery code please also check it.

或者有时使用不正确的数据类型(例如 bool 到整数)通过任何 jQuery 代码将自动值设置为表单字段,也请检查它。

回答by Steve Dowling

I just received this error as well and, in my case, it was caused by the anti-forgery token being applied twice in the same form. The second instance was coming from a partial view so wasn't immediately obvious.

我也刚刚收到此错误,就我而言,这是由于防伪令牌以相同形式应用两次所致。第二个实例来自局部视图,所以不是很明显。

回答by Domin8urMind

validationKey="AutoGenerate"

验证键=“自动生成”

This tells ASP.NET to generate a new encryption key for use in encrypting things like authentication tickets and antiforgery tokens every time the application starts up. If you received a request that used a different key (prior to a restart for instance) to encrypt items of the request (e.g. authenication cookies) that this exception can occur.

这告诉 ASP.NET 生成一个新的加密密钥,用于在每次应用程序启动时加密身份验证票证和防伪令牌等内容。如果您收到的请求使用不同的密钥(例如在重新启动之前)来加密请求的项目(例如身份验证 cookie),则可能会发生此异常。

If you move away from "AutoGenerate" and specify it (the encryption key) specifically, requests that depend on that key to be decrypted correctly and validation will work from app restart to restart. For example:

如果您远离“自动生成”并专门指定它(加密密钥),则依赖于该密钥的请求将被正确解密并验证将从应用程序重新启动到重新启动。例如:

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

You can read to your heart's content at MSDN page: How To: Configure MachineKey in ASP.NET

您可以在 MSDN 页面上仔细阅读:如何:在 ASP.NET 中配置 MachineKey

回答by logical8

Just generate <machineKey .../>tag from a linkfor your framework version and insert into <system.web><system.web/>in Web.config if it does not exist.

只需<machineKey .../>从您的框架版本的链接生成标签,<system.web><system.web/>如果它不存在,则插入到Web.config 中。

Hope this helps.

希望这可以帮助。

回答by ramons03

If you get here from google for your own developer machine showing this error, try to clear cookies in the browser. Clear Browser cookies worked for me.

如果您从 google 到您自己的开发人员机器显示此错误,请尝试清除浏览器中的 cookie。清除浏览器 cookie 对我有用。

回答by armstb01

I ran into this issue in an area of code where I had a view calling a partial view, however, instead of returning a partial view, I was returning a view.

我在代码区域中遇到了这个问题,我有一个视图调用局部视图,但是,我返回的是一个视图,而不是返回一个局部视图。

I changed:

我变了:

return View(index);

返回视图(索引);

to

return PartialView(index);

返回 PartialView(index);

in my control and that fixed my problem.

在我的控制之下,这解决了我的问题。

回答by PussInBoots

If you use Kubernetes and have more than one pod for your app this will most likely cause the request validation to fail because the pod that generates the RequestValidationToken is not necessarily the pod that will validate the token when POSTing back to your application. The fix should be to configure your nginx-controller or whatever ingress resource you are using and tell it to load balance so that each client uses one pod for all communication.

如果您使用 Kubernetes 并且有多个 pod 用于您的应用程序,这很可能会导致请求验证失败,因为生成 RequestValidationToken 的 pod 不一定是在 POST 回您的应用程序时验证令牌的 pod。解决方法应该是配置您的 nginx 控制器或您正在使用的任何入口资源,并告诉它进行负载平衡,以便每个客户端使用一个 pod 进行所有通信。

Update: I managed to fix it by adding the following annotations to my ingress:

更新:我设法通过向我的入口添加以下注释来修复它:

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

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

回答by D.L.MAN

in asp.net Coreyou should set Data Protection system.I test in Asp.Net Core 2.1 or higher.

asp.net Core 中,您应该设置数据保护系统。我在 Asp.Net Core 2.1 或更高版本中进行测试。

there are multi way to do this and you can find more information at Configure Data Protectionand Replace the ASP.NET machineKey in ASP.NET Coreand key storage providers.

有多种方法可以做到这一点,您可以在配置数据保护替换 ASP.NET Core 中的 ASP.NET machineKey密钥存储提供程序中找到更多信息。

  • first way:Local file (easy implementation)

    startup.cscontent:

    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));
       }
    }
    
  • second way:save to db

    The Microsoft.AspNetCore.DataProtection.EntityFrameworkCoreNuGet packagemust be added to the project file

    Add MyKeysConnectionConnectionString to your projects ConnectionStrings in appsettings.json > ConnectionStrings > MyKeysConnection.

    Add MyKeysContextclass to your project.

    MyKeysContext.cscontent:

    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.cscontent:

    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();
       }
    }
    
  • 第一种方式:本地文件(容易实现)

    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.EntityFrameworkCoreNuGet包必须添加到项目文件

    MyKeysConnectionConnectionString添加到您的项目 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();
       }
    }
    

回答by barrypicker

I get this error when the page is old ('stale'). A refresh of the token via a page reload resolves my problem. There seems to be some timeout period.

当页面旧(“陈旧”)时,我收到此错误。通过页面重新加载刷新令牌解决了我的问题。似乎有一些超时时间。

回答by Cosmin

I got this error on .NET Core 2.1. I fixed it by adding the Data Protection service in Startup:

我在 .NET Core 2.1 上遇到了这个错误。我通过在启动中添加数据保护服务来修复它:

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