简体   繁体   中英

TempData fails in a web farm

When deployed to a web farm (basically 2 Windows Server 2016 boxes), the code below fails to read data from TempData. The sequence of events is as follows: UserInfo page is POSTed to, TempData is set, then redirects to the GET of UserInfo. In the GET TempData can't be read.

[HttpPost]
public IActionResult UserInfo(Model model) {
    TempData["Model"] = JsonConvert.SerializeObject(model);
    return RedirectToAction("UserInfo");            
}

[HttpGet]
public IActionResult UserInfo() {
    string serialized = (string)TempData["Model"];
    if (serialized != null) {
        var model = JsonConvert.DeserializeObject<Model>(serialized);
        return View(model);
    } else {
        // nothing here redirect home
        return RedirectToAction("Landing");
    }
}

I get the following error in the std log (but doesn't cause an exception in my code):

warn: Microsoft.AspNetCore.Mvc.ViewFeatures.CookieTempDataProvider[3]
      The temp data cookie .AspNetCore.Mvc.CookieTempDataProvider could not be loaded.

System.Security.Cryptography.CryptographicException: The key {0dd9c024-af79-407b-9820-db7f094975f9} was not found in the key ring.
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status)
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked)
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.CookieTempDataProvider.LoadTempData(HttpContext context)

PS I should mention that this code works in non-web farm IIS instances and on Asure shared hosting.

The exception tells you everything you need to know. It attempted to read the cookie, but decryption failed, specifically because the key could not be found in the data protection key ring. That means you're not sharing data protection between each instance in the farm. Even though it's the same app, each instance is effectively it's own entity. As such, you need to treat it like any other scenario where data protection needs to be shared between sites: namely by using a common key ring store and ensuring that the same application name is used:

services.AddDatProtection()
    .SetApplicationName("Shared Name")
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));

With that, each instance will be able to read the cookies set by other instances, which then will make TempData work between instances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM