ASP.NET Core 中的金鑰儲存體提供者

資料保護系統預設會採用探索機制來判斷密碼編譯金鑰應保存的位置。 開發人員可以覆寫預設探索機制,並手動指定位置。

警告

如果您指定明確的金鑰持續性位置,資料保護系統會取消註冊預設金鑰待用加密機制,因此不會再對待用金鑰進行加密。 建議您另外為生產部署指定明確的金鑰加密機制

檔案系統

若要設定檔案系統型金鑰存放庫,請呼叫 PersistKeysToFileSystem 組態常式,如下所示。 提供指向儲存金鑰的存放庫 DirectoryInfo

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys\"));
}

DirectoryInfo 可以指向本機電腦上的目錄,也可以指向網路共用上的資料夾。 如果指向本機電腦上的目錄 (且情節只有本機電腦上的應用程式需要存取此存放庫),請考慮使用 Windows DPAPI (在 Windows 上) 來加密待用金鑰。 否則,請考慮使用 X.509 憑證來加密待用金鑰。

Azure 儲存體

Azure.Extensions.AspNetCore.DataProtection.Blobs 套件可讓您將資料保護金鑰儲存在 Azure Blob 儲存體中。 金鑰可以在 Web 應用程式的數個執行個體之間共用。 應用程式可以跨多部伺服器共用驗證 cookie 或 CSRF 保護。

若要設定 Azure Blob 儲存體提供者,請呼叫其中一個 PersistKeysToAzureBlobStorage 多載。

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToAzureBlobStorage(new Uri("<blob URI including SAS token>"));
}

如果 Web 應用程式是以 Azure 服務身分執行,則連接字串可用來使用 Azure.Storage.Blobs 向 Azure 儲存體進行驗證。

string connectionString = "<connection_string>";
string containerName = "my-key-container";
string blobName = "keys.xml";
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);

// optional - provision the container automatically
await container.CreateIfNotExistsAsync();

BlobClient blobClient = container.GetBlobClient(blobName);

services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(blobClient);

注意

您可以在 Azure 入口網站的「存取金鑰」區段底下,或執行下列 CLI 命令,找到儲存體帳戶的連接字串:

az storage account show-connection-string --name <account_name> --resource-group <resource_group>

Redis

Microsoft.AspNetCore.DataProtection.StackExchangeRedis 套件可讓您將資料保護金鑰儲存在 Redis 快取中。 金鑰可以在 Web 應用程式的數個執行個體之間共用。 應用程式可以跨多部伺服器共用驗證 cookie 或 CSRF 保護。

Microsoft.AspNetCore.DataProtection.Redis 套件可讓您將資料保護金鑰儲存在 Redis 快取中。 金鑰可以在 Web 應用程式的數個執行個體之間共用。 應用程式可以跨多部伺服器共用驗證 cookie 或 CSRF 保護。

若要在 Redis 上設定,請呼叫其中一個 PersistKeysToStackExchangeRedis 多載:

public void ConfigureServices(IServiceCollection services)
{
    var redis = ConnectionMultiplexer.Connect("<URI>");
    services.AddDataProtection()
        .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
}

若要在 Redis 上設定,請呼叫其中一個 PersistKeysToRedis 多載:

public void ConfigureServices(IServiceCollection services)
{
    var redis = ConnectionMultiplexer.Connect("<URI>");
    services.AddDataProtection()
        .PersistKeysToRedis(redis, "DataProtection-Keys");
}

如需詳細資訊,請參閱下列主題:

登錄

僅適用於 Windows 部署。

有時候應用程式可能沒有檔案系統的寫入權限。 假設應用程式以虛擬服務帳戶的形式執行 (例如 w3wp.exe 的應用程式集區身分識別)。 在這些情況下,系統管理員可以佈建服務帳戶身分識別可存取的登錄機碼。 呼叫 PersistKeysToRegistry 擴充方法,如下所示。 提供指向應儲存密碼編譯金鑰的位置 RegistryKey

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys", true));
}

重要

我們建議使用 Windows DPAPI 來加密待用金鑰。

Entity Framework Core

Microsoft.AspNetCore.DataProtection.EntityFrameworkCore 套件提供一種機制,可讓您使用 Entity Framework Core 將資料保護金鑰儲存至資料庫。 Microsoft.AspNetCore.DataProtection.EntityFrameworkCore NuGet 套件必須新增至專案檔,它不屬於 Microsoft.AspNetCore.App 中繼套件

使用此套件時,金鑰可以跨 Web 應用程式的多個執行個體共用。

若要設定 EF Core 提供者,請呼叫 PersistKeysToDbContext 方法:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

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

    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

如果您想要查看翻譯為英文以外語言的程式碼註解,請在此 GitHub 討論問題中告訴我們。

泛型參數 TContext 必須繼承自 DbContext 並實作 IDataProtectionKeyContext

using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

namespace WebApp1
{
    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; }
    }
}

建立 DataProtectionKeys 資料表。

套件管理員主控台 (PMC) 視窗中執行下列命令:

Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext

MyKeysContext 是上述程式碼範例中定義的 DbContext。 如果您使用不同名稱的 DbContext,請將 DbContext 名稱取代為 MyKeysContext

DataProtectionKeys 類別/實體採用下表所示的結構。

屬性/欄位 CLR 型別 SQL 型別
Id int int、PK、IDENTITY(1,1),而非 null
FriendlyName string nvarchar(MAX)、null
Xml string nvarchar(MAX)、null

自訂金鑰存放庫

如果內建機制不合適,開發人員可以藉由提供自訂 IXmlRepository 來指定自己的金鑰持續性機制。