防伪令牌无法解密

时间:2014-05-01 04:53:48

标签: asp.net-mvc asp.net-mvc-4

我有一张表格:

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

和行动:

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

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

  

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

我尝试添加到webconfig:

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

但错误仍然偶尔出现

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

或者有时一个自动值设置不正确的数据类型,如bool到整数到表单字段的任何jQuery代码请检查它。

12 个答案:

答案 0 :(得分:118)

我刚收到此错误,在我的情况下,它是由防伪令牌以相同的形式应用两次引起的。第二个例子来自局部视图,所以并不是很明显。

答案 1 :(得分:22)

validationKey =&#34; AutoGenerate&#34;

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

如果你离开&#34; AutoGenerate&#34;并具体指定它(加密密钥),依赖于该密钥的请求被正确解密,验证将从app restart重新启动。例如:

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

您可以在MSDN页面上阅读您心中的内容:How To: Configure MachineKey in ASP.NET

答案 2 :(得分:9)

只需从a link为您的框架版本生成<machineKey .../>标记,如果不存在,则在Web.config中插入<system.web><system.web/>

希望这有帮助。

答案 3 :(得分:5)

如果您从谷歌那里找到显示此错误的自己的开发者计算机,请尝试在浏览器中清除Cookie。清除浏览器cookie对我有用。

答案 4 :(得分:4)

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

有多种方法可以执行此操作,您可以在Configure Data ProtectionReplace the ASP.NET machineKey in ASP.NET Corekey storage providers上找到更多信息。

  • 第一种方式:本地文件(易于实施)

    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 package必须添加到项目文件中

    MyKeysConnection ConnectionString添加到您的项目中 appsettings.json > ConnectionStrings > MyKeysConnection中的ConnectionStrings。

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

答案 5 :(得分:3)

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

我改变了:

返回视图(索引);

返回PartialView(索引);

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

答案 6 :(得分:1)

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

答案 7 :(得分:1)

.NET Core 2.1出现此错误。我通过在启动中添加数据保护服务来修复它:

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

答案 8 :(得分:1)

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

更新:我设法通过在入口中添加以下注释来解决此问题:

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

答案 9 :(得分:1)

对于这个问题,我找到了一个非常有趣的解决方法,至少在我的情况下是这样。我的视图是使用 ajax 在一个 div 中动态加载带有表单的部分视图,所有这些都在另一个表单中。主表单提交没有问题,其中一个部分有效,但另一个无效。部分视图之间的唯一区别是在一个正在工作的视图的末尾是一个空的脚本标记

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

我删除了它,果然我得到了错误。我在另一个局部视图中添加了一个空的脚本标签,狗走了,它工作了!我知道这不是最干净的……但就速度和开销而言……

答案 10 :(得分:0)

为此,我的解决方法是获取cookie和令牌值,如下所示:

AntiForgery.GetTokens(null, out var cookieToken, out var formToken);

答案 11 :(得分:0)

您认为视图中的多个 @Html.AntiForgeryToken()