簡體   English   中英

交換 Azure Web App 部署槽會注銷 ASP.NET Core RC2 中的所有用戶

[英]Swapping Azure Web App deployment slots logs out all users in ASP.NET Core RC2

每當我更新作為 Azure Web 應用程序運行的 ASP.NET Core RC2 網站時,它都會注銷所有用戶。 這似乎與將暫存部署槽交換到生產有關(我使用從 VS 到暫存的 web 部署,並將其設置為自動交換到生產)。 如果我直接更新生產槽,那很好,但我不想這樣做。 我不知道如何配置它,將不勝感激!

這是我現在配置它的方式,我的網站只允許直接登錄(沒有 Facebook 登錄等):

在啟動中的 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();

並在啟動時配置

app.UseIdentity();

經過大量研究……我認為我已經在工作。

因此,對於任何想要使用身份信息進行登錄的ASP.NET Core RC2網站,並希望將其托管在Azure Web應用程序上,並且想要使用部署插槽通過交換進行更新的人, 並不想讓所有人用戶在每次更新網站時都會注銷...請繼續閱讀!

**通常,Azure為您提供了一些神奇的默認配置,使單個Web App中的所有實例可以協同工作。 部署插槽的問題在於,它實際上就像兩個完全獨立的Web Apps一樣,因此所有魔力都消失了。

您需要正確配置Data Protection才能執行此操作。 這有點令人困惑,因為.NET Core Identity文檔沒有明確提及依賴或要求您正確配置Data Protection的情況,但是確實如此。 數據保護功能是它在后台用來加密應用程序登錄cookie的功能。

ConfigureServices中需要以下代碼:

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

services.AddSingleton<IXmlRepository, CustomDataProtectionRepository>();

每件的說明:

  1. 設置應用程序名稱可讓您在使用同一應用程序名稱的多個應用程序之間共享受保護的數據。 可能並非所有情況都需要,但對我們而言並不有害。
  2. 您需要使用在兩個部署槽之間都一致的自定義密鑰加密方法。 默認值特定於每個部署插槽,並且只能在該插槽中使用。 如果您看靜態的密鑰加密,則默認情況下,Azure使用Windows DPAPI。 不會為我們的目的工作。 因此,我選擇使用證書,只需輸入在Azure門戶中看到的指紋即可。 注意:對於那些討厭證書及其周圍所有術語的人,.NET Core文檔說您需要支持CAPI私鑰的X.509證書,否則它將無法正常工作。 等等等等使用您為您的網站獲得的SSL證書,它應該可以正常工作。
  3. 順便說一句:您必須做一些額外的搜索才能真正使用證書。 數據保護文檔讓您陷入Azure的困擾...僅使用上面的代碼,當部署到Azure時,您可能會遇到500錯誤。 首先,請確保您已將證書上載到Web應用程序的“自定義域和SSL”部分。 其次,您需要添加WEBSITE_LOAD_CERTIFICATES應用程序設置並將證書的指紋添加到該應用程序才能使用它。 請參閱在Azure網站上使用證書
  4. 設置用於加密數據的證書后,它會破壞關於存儲數據位置的任何默認配置-Azure將其存儲在您的所有實例都可以默認訪問的共享文件夾中(默認值此處介紹了數據保護默認值 ) 。 但是不同的部署插槽是分開的...因此內置文件系統和注冊表選項無濟於事。 您必須編寫一個自定義實現,如下所述: 密鑰存儲提供程序 但是,等等,自定義密鑰存儲庫底部的部分是1-liner,沒有鏈接或有關如何將其連接的說明...您真的需要在這里閱讀: 密鑰管理 ,轉到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<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);
}

如果以這種方式存儲,這是一個示例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"
  }
}

我更新了 EricksonG 的答案以包含一些新庫。 這解決了問題,而且實施起來很快。

您將需要這些軟件包:

 Microsoft.AspNetCore.DataProtection
 Azure.Extensions.AspNetCore.DataProtection.Blobs
 Azure.Extensions.AspNetCore.DataProtection.Keys

這是我的代碼版本。

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

您可能需要確保容器存在,但這肯定會自動處理創建 blob 和鍵。 你甚至不必見他們。

另外:docs 建議這應該在您的配置中先於其他任何可能進行身份驗證的操作,因為這些工具有時對數據保護有自己的看法。

應用設置:

{
  "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. 
  }
}

保護:按原樣,這並不是那么安全。 讓它正常工作,然后如果您需要更多安全性,請通過 .ProtectKeysWithAzureKeyVault() 或其他擴展方法之一執行 Key Vault 保護來進一步提高安全性。 當然,將 KeyVault 用於連接字符串也是一個好主意。

應用程序名稱: .SetApplicationName() 行是可選的; 它有助於在應用程序之間隔離或共享數據。 來自文檔:默認情況下,數據保護系統根據應用程序的內容根路徑將應用程序彼此隔離,即使它們共享相同的物理密鑰存儲庫。 這會阻止應用程序了解彼此的受保護負載。

更多: https : //docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-5.0

謝謝布萊恩。 我現在有這個工作。 我認為它需要這個和 web 配置文件中的機器密鑰。 我說我認為是因為在我交換插槽然后單擊瀏覽按鈕后,我仍然看到我的注冊和登錄按鈕而不是個人資料信息,但是一旦我導航到另一個頁面,我就會看到個人資料信息。 我很欣賞回應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM