[英]Swapping Azure Web App deployment slots logs out all users in ASP.NET Core RC2
Whenever I updated my ASP.NET Core RC2 website running on as an Azure Web App, it logs out all users.每当我更新作为 Azure Web 应用程序运行的 ASP.NET Core RC2 网站时,它都会注销所有用户。 It seems to be related to swapping a staging deployment slot to production (I use web deploy from VS to staging, and have it set to auto-swap to production).
这似乎与将暂存部署槽交换到生产有关(我使用从 VS 到暂存的 web 部署,并将其设置为自动交换到生产)。 If I do a direct update of the production slot it's fine, but I don't want to do that.
如果我直接更新生产槽,那很好,但我不想这样做。 I am at a loss as to how to configure this, help would be appreciated!
我不知道如何配置它,将不胜感激!
Here is how I have it configured right now, my site only allows logging in directly (no facebook login etc.):这是我现在配置它的方式,我的网站只允许直接登录(没有 Facebook 登录等):
In ConfigureServices in Startup在启动中的 ConfigureServices 中
// found some post that said this would help... doesn't seem to work...
services.AddDataProtection()
.SetApplicationName("myweb");
services.AddIdentity<MyUser, MyRole>(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<MyUserStore>() // custom stores to hook up our old databases to new identity system
.AddRoleStore<MyRoleStore>()
.AddDefaultTokenProviders();
And in Configure in Startup并在启动时配置
app.UseIdentity();
After much research... I think that I have this working. 经过大量研究……我认为我已经在工作。
So for anyone who wants an ASP.NET Core RC2 website that uses the Identity stuff for login, and wants to host it on an Azure Web App, and wants to use the Deployment Slots to do updates via swapping, and doesn't want every user to get logged out every time the website is updated... read on! 因此,对于任何想要使用身份信息进行登录的ASP.NET Core RC2网站,并希望将其托管在Azure Web应用程序上,并且想要使用部署插槽通过交换进行更新的人, 并不想让所有人用户在每次更新网站时都会注销...请继续阅读!
** Usually, Azure gives you some magical default configuration that makes all of the instances in a single Web App work together. **通常,Azure为您提供了一些神奇的默认配置,使单个Web App中的所有实例可以协同工作。 The issue with deployment slots is that it essentially acts like two completely separate Web Apps, so all the magic is gone.
部署插槽的问题在于,它实际上就像两个完全独立的Web Apps一样,因此所有魔力都消失了。
You need to configure Data Protection correctly to make this work. 您需要正确配置Data Protection才能执行此操作。 It is a bit confusing because the documentation for .NET Core Identity makes no explicit mention of depending on or requiring that you configure Data Protection correctly, but it does.
这有点令人困惑,因为.NET Core Identity文档没有明确提及依赖或要求您正确配置Data Protection的情况,但是确实如此。 Data Protection is what it uses under the hood to encrypt the application login cookie.
数据保护功能是它在后台用来加密应用程序登录cookie的功能。
The following code is needed in ConfigureServices: ConfigureServices中需要以下代码:
services.AddDataProtection()
.SetApplicationName("myweb")
.ProtectKeysWithCertificate("thumbprint");
services.AddSingleton<IXmlRepository, CustomDataProtectionRepository>();
Explanation of each piece: 每件的说明:
And OMG finally we have it working. 最终,OMG我们开始运作了。 Enjoy the 500% decrease in lost password customer service requests ;)
享受减少500%的密码丢失客户服务请求;)
I tried to piece together a number of articles include the one here into a complete solution. 我试图整理一些文章,其中包括一个完整的解决方案。 Here is what I came up with.
这是我想出的。 Original blog post: http://intellitect.com/staying-logged-across-azure-app-service-swap/
原始博客文章: 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<string>("DataProtection:StorageUrl");
string sasToken = Configuration.GetValue<string>("DataProtection:SasToken");
string containerName = Configuration.GetValue<string>("DataProtection:ContainerName");
string applicationName = Configuration.GetValue<string>("DataProtection:ApplicationName");
string blobName = Configuration.GetValue<string>("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);
}
Here is a sample appsettings.json if they are stored that way. 如果以这种方式存储,这是一个示例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=a.b.c.d-w.x.y.z&spr=https&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"ContainerName": "data-protection-container-name", // All lower case with dashes and numbers.
"BlobName": "data-protection-blob-name"
}
}
I updated EricksonG's answer to include some new libraries.我更新了 EricksonG 的答案以包含一些新库。 This solves the problem and it's quick to implement.
这解决了问题,而且实施起来很快。
You will need these packages:您将需要这些软件包:
Microsoft.AspNetCore.DataProtection
Azure.Extensions.AspNetCore.DataProtection.Blobs
Azure.Extensions.AspNetCore.DataProtection.Keys
Here's my version of the code.这是我的代码版本。
var connectionString = configuration["DataProtection:ConnectionString"];
var containerName = configuration["DataProtection:ContainerName"];
var applicationName = configuration["DataProtection:ApplicationName"];
var blobName = configuration["DataProtection:BlobName"];
services.AddDataProtection()
.SetApplicationName(applicationName) // This is optional. See below.
.PersistKeysToAzureBlobStorage(connectionString, containerName, blobName);
You might need to make sure the container exists, however this will definitely handle creating blob and the keys automatically.您可能需要确保容器存在,但这肯定会自动处理创建 blob 和键。 You never even have to see them.
你甚至不必见他们。
Also: docs suggests this should go in your config before anything else that might be doing auth, because those tools sometimes have their own take on Data Protection.另外:docs 建议这应该在您的配置中先于其他任何可能进行身份验证的操作,因为这些工具有时对数据保护有自己的看法。
AppSettings:应用设置:
{
"DataProtection": {
"ApplicationName": "AppName", // Can technically be anything. See below for details on this.
"ConnectionString": "<Your key from azure>",
"ContainerName": "data-protection", // All lower case with dashes and numbers. There's no need to change this, but you can.
"BlobName": "data-protection-keys" // Same.
}
}
Protection: As-is, this is not all that secure.保护:按原样,这并不是那么安全。 Get it working, and then if you need more security, take this further by doing Key Vault protection via .ProtectKeysWithAzureKeyVault(), or one of the other extension methods.
让它正常工作,然后如果您需要更多安全性,请通过 .ProtectKeysWithAzureKeyVault() 或其他扩展方法之一执行 Key Vault 保护来进一步提高安全性。 It would also be a good idea to use KeyVault for the connection string, of course.
当然,将 KeyVault 用于连接字符串也是一个好主意。
Application Name: The .SetApplicationName() line is optional;应用程序名称: .SetApplicationName() 行是可选的; it helps isolate or share data between apps.
它有助于在应用程序之间隔离或共享数据。 From the docs: by default, the Data Protection system isolates apps from one another based on their content root paths, even if they're sharing the same physical key repository.
来自文档:默认情况下,数据保护系统根据应用程序的内容根路径将应用程序彼此隔离,即使它们共享相同的物理密钥存储库。 This prevents the apps from understanding each other's protected payloads.
这会阻止应用程序了解彼此的受保护负载。
More: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-5.0更多: https : //docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-5.0
Thanks Brian.谢谢布莱恩。 I have this working now.
我现在有这个工作。 I think it required both this and the machine key in the web configuration file.
我认为它需要这个和 web 配置文件中的机器密钥。 I say I think because after I swap slots and then click the browse button I still see my register and login buttons instead of the profile info but as soon as I navigate to another page I see the profile info.
我说我认为是因为在我交换插槽然后单击浏览按钮后,我仍然看到我的注册和登录按钮而不是个人资料信息,但是一旦我导航到另一个页面,我就会看到个人资料信息。 I appreciate the response.
我很欣赏回应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.