交换Azure Web App部署槽会注销ASP.NET Core RC2中的所有用户

每当我更新作为Azure Web App运行的ASP.NET Core RC2网站时,它都会注销所有用户。 这似乎与将暂存部署槽交换到生产相关(我使用从VS到登台的Web部署,并将其设置为自动交换到生产)。 如果我直接更新生产槽,那很好,但我不想这样做。 我不知道如何配置这个,帮助将不胜感激!

这是我现在如何配置它,我的网站只允许直接登录(没有Facebook登录等):

在Startup中的ConfigureServices中

// found some post that said this would help... doesn't seem to work... services.AddDataProtection() .SetApplicationName("myweb"); services.AddIdentity(options => { options.Cookies.ApplicationCookie.CookieDomain = settings.CookieDomain; // cookie domain lets us share cookies across subdomains options.Cookies.ApplicationCookie.LoginPath = new PathString("/account/login"); options.Cookies.ApplicationCookie.ReturnUrlParameter = "ret"; options.Cookies.ApplicationCookie.CookieSecure = CookieSecureOption.Never; // TODO: revisit site-wide https // allow login cookies to last for 30 days from last use options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(60); options.Cookies.ApplicationCookie.SlidingExpiration = true; // I think this needs to at least be longer than cookie expiration to prevent security stamp from becoming invalid before the cookie? options.SecurityStampValidationInterval = TimeSpan.FromDays(90); }) .AddUserStore() // custom stores to hook up our old databases to new identity system .AddRoleStore() .AddDefaultTokenProviders(); 

在Configure in Startup中

 app.UseIdentity(); 

经过大量研究……我认为我有这个工作。

因此,对于任何想要使用Identity Core登录的ASP.NET Core RC2网站,并希望在Azure Web App上托管它,并希望使用部署插槽通过交换进行更新,并且希望每个人用户每次更新网站时都要注销…继续阅读!

**通常,Azure会为您提供一些神奇的默认配置,使一个Web应用程序中的所有实例能够协同工作。 部署插槽的问题在于它本质上就像两个完全独立的Web应用程序,所以所有的魔力都消失了。

您需要正确配置Data Protection才能使其正常工作。 这有点令人困惑,因为.NET Core Identity的文档没有明确提及依赖或要求您正确配置Data Protection,但确实如此。 数据保护是它在引擎盖下用来加密应用程序登录cookie的方式。

ConfigureServices中需要以下代码:

 services.AddDataProtection() .SetApplicationName("myweb") .ProtectKeysWithCertificate("thumbprint"); services.AddSingleton(); 

每件作品说明:

  1. 通过设置应用程序名称,您可以跨使用此相同应用程序名称的多个应用程序共享受保护数据 可能并非所有情况都需要,但对我们的情况没有伤害。
  2. 您需要使用在两个部署插槽中一致的自定义密钥加密方法。 默认值特定于每个部署插槽,并且只能在该插槽中使用。 如果您查看静态时的密钥加密 ,Azure默认使用Windows DPAPI。 不适合我们的目的。 所以我选择使用证书,只需输入Azure门户中的指纹即可。 注意:对于那些讨厌证书及其周围所有术语的人,.NET Core文档说您需要一个支持CAPI私钥的X.509证书,否则它将无法运行。 blah blah blah blah使用你为你的网站获得的SSL证书,它应该工作得很好。
  3. 旁白:你必须做一些额外的谷歌搜索才能真正使用证书工作。 在Azure的情况下,数据保护文档会让您挂起……只需使用上面的代码,部署到Azure时可能会出现500错误。 首先,确保您已将证书上载到Web App的“自定义域和SSL”部分。 其次,您需要添加WEBSITE_LOAD_CERTIFICATES应用程序设置并将证书的指纹添加到该设置以便使用它。 请参阅azure网站中的使用证书 。
  4. 设置证书以加密数据后……它会删除有关存储数据位置的任何默认配置 – Azure会将其存储在默认情况下所有实例都可以访问的共享文件夹中(此处描述的默认值为数据保护默认值 ) 。 但是不同的部署插槽是分开的…所以内置的文件系统和注册表选项没有帮助。 您必须编写如下所述的自定义实现: 密钥存储提供程序 。 但是哦等等……自定义密钥存储库底部的部分是一个单行程序,没有关于如何连接它的链接或解释……你真的需要在这里阅读: 密钥管理 ,转到IXmlRepository部分。 不幸的是,除了你需要做的事情之外,IDataProtectionBuilder还有一些方便的扩展,因此我们将这个自定义IXmlRepository注册到服务提供者的行。 尽管该接口具有令人震惊的通用名称,但它只会影响数据保护,并且不会混淆您的其他内容。
  5. 未显示的是CustomDataProtectionRepository的实现。 我使用Azure blob存储。 这是一个非常简单的界面,如果您需要帮助,请发表评论。

而OMG终于有了它的工作。 享受丢失密码客户服务请求500%减少;)

我试图拼凑一些文章,包括这里的一个完整的解决方案。 这就是我想出的。 原创博文: http : //intellitect.com/staying-logged-across-azure-app-service-swap/

 // Add Data Protection so that cookies don't get invalidated when swapping slots. string storageUrl = Configuration.GetValue("DataProtection:StorageUrl"); string sasToken = Configuration.GetValue("DataProtection:SasToken"); string containerName = Configuration.GetValue("DataProtection:ContainerName"); string applicationName = Configuration.GetValue("DataProtection:ApplicationName"); string blobName = Configuration.GetValue("DataProtection:BlobName"); // If we have values for all these things set up the data protection store in Azure. if (storageUrl != null && sasToken != null && containerName != null && applicationName != null && blobName != null) { // Create the new Storage URI Uri storageUri = new Uri($"{storageUrl}{sasToken}"); //Create the blob client object. CloudBlobClient blobClient = new CloudBlobClient(storageUri); //Get a reference to a container to use for the sample code, and create it if it does not exist. CloudBlobContainer container = blobClient.GetContainerReference(containerName); container.CreateIfNotExists(); services.AddDataProtection() .SetApplicationName(applicationName) .PersistKeysToAzureBlobStorage(container, blobName); } 

以下是appsettings.json示例,如果它们以这种方式存储的话。

 { "DataProtection": { "ApplicationName": "AppName", "StorageUrl": "https://BlobName.blob.core.windows.net", "SasToken": "?sv=YYYY-MM-DD&ss=x&srt=xxx&sp=xxxxxx&se=YYYY-MM-DDTHH:MM:SSZ&st=YYYY-MM-DDTHH:MM:SSZ&sip=abcd-wxyz&spr=https&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "ContainerName": "data-protection-container-name", // All lower case with dashes and numbers. "BlobName": "data-protection-blob-name" } }