Konfigurowanie ochrony danych na platformie ASP.NET Core
Gdy system ochrony danych jest inicjowany, stosuje ustawienia domyślne na podstawie środowiska operacyjnego. Te ustawienia są odpowiednie dla aplikacji działających na jednej maszynie. Istnieją jednak przypadki, w których deweloper może chcieć zmienić ustawienia domyślne:
- Aplikacja jest rozłożona na wiele maszyn.
- Ze względów zgodności.
W tych scenariuszach system ochrony danych oferuje zaawansowany interfejs API konfiguracji.
Ostrzeżenie
Podobnie jak w przypadku plików konfiguracji pierścień kluczy ochrony danych powinien być chroniony przy użyciu odpowiednich uprawnień. Możesz wybrać szyfrowanie kluczy w witrynie rest, ale nie uniemożliwia to cyberatakom tworzenia nowych kluczy. W związku z tym ma to wpływ na bezpieczeństwo aplikacji. Lokalizacja magazynu skonfigurowana przy użyciu usługi Data Protection powinna mieć ograniczony dostęp do samej aplikacji, podobnie jak w przypadku ochrony plików konfiguracji. Jeśli na przykład zdecydujesz się przechowywać pierścień kluczy na dysku, użyj uprawnień systemu plików. Upewnij się, że tylko identity w obszarze, w którym działa aplikacja internetowa, ma dostęp do odczytu, zapisu i tworzenia dostępu do tego katalogu. Jeśli używasz usługi Azure Blob Storage, tylko aplikacja internetowa powinna mieć możliwość odczytu, zapisu lub tworzenia nowych wpisów w magazynie obiektów blob itp.
Metoda rozszerzenia zwraca wartość AddDataProtection IDataProtectionBuilder. IDataProtectionBuilder
Uwidacznia metody rozszerzeń, które można połączyć w celu skonfigurowania opcji ochrony danych.
Uwaga
Ten artykuł został napisany dla aplikacji działającej w kontenerze platformy Docker. W kontenerze platformy Docker aplikacja zawsze ma tę samą ścieżkę i dlatego ta sama aplikacja dyskryminuje. Aplikacje, które muszą być uruchamiane w wielu środowiskach (na przykład w środowisku lokalnym i wdrożonym), muszą ustawić domyślną dyskryminującą aplikację dla środowiska. Uruchamianie aplikacji w wielu środowiskach wykracza poza zakres tego artykułu.
Następujące pakiety NuGet są wymagane dla rozszerzeń ochrony danych używanych w tym artykule:
ProtectKeysWithAzureKeyVault
Zaloguj się do platformy Azure przy użyciu interfejsu wiersza polecenia, na przykład:
az login
Aby zarządzać kluczami za pomocą usługi Azure Key Vault, skonfiguruj system za pomocą ProtectKeysWithAzureKeyVault polecenia w programie Program.cs
. blobUriWithSasToken
to pełny identyfikator URI, w którym powinien być przechowywany plik klucza. Identyfikator URI musi zawierać token SAS jako parametr ciągu zapytania:
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
.ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());
Aby aplikacja komunikowała się i autoryzować się za pomocą usługi KeyVault, należy dodać pakiet platformy Azure.Identity
Ustaw lokalizację przechowywania pierścienia kluczy (na przykład PersistKeysToAzureBlobStorage). Lokalizacja musi być ustawiona, ponieważ wywołanie ProtectKeysWithAzureKeyVault
implementuje IXmlEncryptor funkcję , która wyłącza ustawienia automatycznej ochrony danych, w tym lokalizację przechowywania pierścienia kluczy. W poprzednim przykładzie użyto usługi Azure Blob Storage do utrwalania pierścienia kluczy. Aby uzyskać więcej informacji, zobacz Dostawcy magazynu kluczy: Azure Storage. Możesz również utrwalać pierścień kluczy lokalnie za pomocą funkcji PersistKeysToFileSystem.
Jest keyIdentifier
to identyfikator klucza magazynu kluczy używany do szyfrowania kluczy. Na przykład klucz utworzony w magazynie kluczy o nazwie dataprotection
w obiekcie contosokeyvault
ma identyfikator https://contosokeyvault.vault.azure.net/keys/dataprotection/
klucza . Podaj aplikację z uprawnieniami Pobierz, Odpakuj klucz i Zawij klucz do magazynu kluczy.
ProtectKeysWithAzureKeyVault
Przeciążenia:
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, Uri, TokenCredential) umożliwia użycie identyfikatora URI keyIdentifier i tokenCredential, aby umożliwić systemowi ochrony danych korzystanie z magazynu kluczy.
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, IKeyEncryptionKeyResolver) umożliwia korzystanie z ciągu keyIdentifier i IKeyEncryptionKeyResolver, aby umożliwić systemowi ochrony danych korzystanie z magazynu kluczy.
Jeśli aplikacja korzysta ze starszych pakietów platformy Azure (Microsoft.AspNetCore.DataProtection.AzureStorage i Microsoft.AspNetCore.DataProtection.AzureKeyVault), zalecamy usunięcie tych odwołań i uaktualnienie do plików Azure.Extensions.AspNetCore.DataProtection.Blobs i Azure.Extensions.AspNetCore.DataProtection.Keys. Te pakiety to miejsce, w którym są udostępniane nowe aktualizacje, oraz rozwiązywanie niektórych kluczowych problemów z zabezpieczeniami i stabilnością starszych pakietów.
builder.Services.AddDataProtection()
// This blob must already exist before the application is run
.PersistKeysToAzureBlobStorage("<storageAccountConnectionString", "<containerName>", "<blobName>")
// Removing this line below for an initial run will ensure the file is created correctly
.ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());
PersistKeysToFileSystem
Aby przechowywać klucze w udziale UNC zamiast w domyślnej lokalizacji %LOCALAPPDATA% , skonfiguruj system za pomocą polecenia PersistKeysToFileSystem:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
Ostrzeżenie
Jeśli zmienisz lokalizację trwałości klucza, system nie będzie już automatycznie szyfrować kluczy w restlokalizacji , ponieważ nie wie, czy dpAPI jest odpowiednim mechanizmem szyfrowania.
PersistKeysToDbContext
Aby przechowywać klucze w bazie danych przy użyciu elementu EntityFramework, skonfiguruj system przy użyciu pakietu Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
builder.Services.AddDataProtection()
.PersistKeysToDbContext<SampleDbContext>();
Powyższy kod przechowuje klucze w skonfigurowanej bazie danych. Używany kontekst bazy danych musi implementować IDataProtectionKeyContext
element . IDataProtectionKeyContext
uwidacznia właściwość DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;
Ta właściwość reprezentuje tabelę, w której są przechowywane klucze. Utwórz tabelę ręcznie lub za pomocą DbContext
funkcji Migracje. Aby uzyskać więcej informacji, zobacz DataProtectionKey.
ProtectKeysWith*
System można skonfigurować tak, aby chronił klucze, rest wywołując dowolny z interfejsów API konfiguracji ProtectKeysWith* . Rozważmy poniższy przykład, który przechowuje klucze w udziale UNC i szyfruje te klucze przy rest użyciu określonego certyfikatu X.509:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);
Możesz podać element X509Certificate2 do ProtectKeysWithCertificateelementu , taki jak certyfikat załadowany z pliku:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));
Więcej przykładów i omówienie wbudowanych mechanizmów szyfrowania kluczy można znaleźć w temacie Szyfrowanie kluczy at Rest .
UnprotectKeysWithAnyCertificate
Certyfikaty i klucze rest odszyfrowywania można wymieniać przy użyciu tablicy certyfikatów X509Certificate2 za UnprotectKeysWithAnyCertificatepomocą polecenia :
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));
SetDefaultKeyLifetime
Aby skonfigurować system do używania okresu istnienia klucza 14 dni zamiast domyślnego 90 dni, użyj polecenia SetDefaultKeyLifetime:
builder.Services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
SetApplicationName
Domyślnie system ochrony danych izoluje aplikacje od siebie na podstawie ścieżek głównych zawartości, nawet jeśli współużytkują to samo repozytorium kluczy fizycznych. Ta izolacja uniemożliwia aplikacjom zrozumienie ładunków chronionych przez siebie.
Aby udostępnić chronione ładunki między aplikacjami:
- Skonfiguruj SetApplicationName w każdej aplikacji tę samą wartość.
- Użyj tej samej wersji stosu interfejsu API ochrony danych w aplikacjach. Wykonaj jedną z następujących czynności w plikach projektu aplikacji:
- Odwołuj się do tej samej wersji platformy udostępnionej za pośrednictwem Microsoft.AspNetCore.App metapakiet.
- Odwołuje się do tej samej wersji pakietu usługi Data Protection.
builder.Services.AddDataProtection()
.SetApplicationName("<sharedApplicationName>");
SetApplicationName program wewnętrznie ustawia wartość DataProtectionOptions.ApplicationDiscriminator. W celach rozwiązywania problemów wartość przypisana dyskryminującemu przez platformę może być rejestrowana przy użyciu następującego kodu umieszczonego po WebApplication skompilowaniu elementu Program.cs
:
var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
.Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);
Aby uzyskać więcej informacji na temat sposobu użycia dyskryminującego, zobacz następujące sekcje w dalszej części tego artykułu:
Ostrzeżenie
Na platformie .NET 6 WebApplicationBuilder normalizuje ścieżkę katalogu głównego zawartości, aby zakończyć ciąg .DirectorySeparatorChar Na przykład w systemie Windows ścieżka główna zawartości kończy się na \
i w systemie Linux /
. Inne hosty nie normalizują ścieżki. Większość aplikacji migrujących z HostBuilder programu lub WebHostBuilder nie będzie współdzielić tej samej nazwy aplikacji, ponieważ nie będzie miała zakończenia .DirectorySeparatorChar
Aby obejść ten problem, usuń znak separatora katalogu i ręcznie ustaw nazwę aplikacji, jak pokazano w poniższym kodzie:
using Microsoft.AspNetCore.DataProtection;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var trimmedContentRootPath = builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);
builder.Services.AddDataProtection()
.SetApplicationName(trimmedContentRootPath);
var app = builder.Build();
app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);
app.Run();
DisableAutomaticKeyGeneration
Może istnieć scenariusz, w którym nie chcesz, aby aplikacja automatycznie rzutować klucze (tworzyć nowe klucze) w miarę zbliżania się do wygaśnięcia. Jednym z przykładów tego scenariusza mogą być aplikacje skonfigurowane w relacji podstawowej/pomocniczej, gdzie tylko podstawowa aplikacja jest odpowiedzialna za kluczowe problemy z zarządzaniem, a aplikacje pomocnicze mają po prostu widok pierścienia kluczy tylko do odczytu. Aplikacje pomocnicze można skonfigurować tak, aby traktować pierścień kluczy jako tylko do odczytu, konfigurując system przy użyciu polecenia DisableAutomaticKeyGeneration:
builder.Services.AddDataProtection()
.DisableAutomaticKeyGeneration();
Izolacja dla aplikacji
Gdy system ochrony danych jest dostarczany przez hosta ASP.NET Core, automatycznie izoluje aplikacje od siebie, nawet jeśli te aplikacje są uruchomione na tym samym koncie procesu roboczego i używają tego samego głównego materiału kluczy. Jest to podobne do modyfikatora IsolateApps z elementu System.Web <machineKey>
.
Mechanizm izolacji działa, biorąc pod uwagę każdą aplikację na komputerze lokalnym jako unikatową dzierżawę, w związku z czym IDataProtector rooted dla danej aplikacji automatycznie uwzględnia identyfikator aplikacji jako dyskryminujący (ApplicationDiscriminator). Unikatowy identyfikator aplikacji to ścieżka fizyczna aplikacji:
- W przypadku aplikacji hostowanych w usługach IIS unikatowy identyfikator to ścieżka fizyczna usług IIS aplikacji. Jeśli aplikacja jest wdrażana w środowisku farmy sieci Web, ta wartość jest stabilna przy założeniu, że środowiska usług IIS są podobnie skonfigurowane na wszystkich maszynach w farmie sieci Web.
- W przypadku aplikacji hostowanych samodzielnie na Kestrel serwerze unikatowy identyfikator to ścieżka fizyczna do aplikacji na dysku.
Unikatowy identyfikator jest przeznaczony do przetrwania resetowania — zarówno pojedynczej aplikacji, jak i samej maszyny.
Ten mechanizm izolacji zakłada, że aplikacje nie są złośliwe. Złośliwa aplikacja zawsze może mieć wpływ na dowolną inną aplikację działającą na tym samym koncie procesu roboczego. W udostępnionym środowisku hostingu, w którym aplikacje są wzajemnie niezaufane, dostawca hostingu powinien podjąć kroki w celu zapewnienia izolacji na poziomie systemu operacyjnego między aplikacjami, w tym oddzielenia bazowych repozytoriów kluczy aplikacji.
Jeśli system ochrony danych nie jest udostępniany przez hosta platformy ASP.NET Core (na przykład w przypadku utworzenia wystąpienia za pośrednictwem konkretnego DataProtectionProvider
typu) izolacja aplikacji jest domyślnie wyłączona. Gdy izolacja aplikacji jest wyłączona, wszystkie aplikacje wspierane przez ten sam materiał kluczy mogą współdzielić ładunki, o ile zapewniają odpowiednie cele. Aby zapewnić izolację aplikacji w tym środowisku, wywołaj SetApplicationName
metodę w obiekcie konfiguracji i podaj unikatową nazwę dla każdej aplikacji.
Ochrona danych i izolacja aplikacji
Rozważ następujące kwestie dotyczące izolacji aplikacji:
Gdy wiele aplikacji jest wskazywanych na to samo repozytorium kluczy, intencją jest to, że aplikacje współużytkują ten sam materiał klucza głównego. Ochrona danych jest opracowywana przy założeniu, że wszystkie aplikacje współużytkujące pierścień kluczy mogą uzyskiwać dostęp do wszystkich elementów w tym pierścieniu kluczy. Unikatowy identyfikator aplikacji służy do izolowania kluczy specyficznych dla aplikacji pochodzących z kluczy dostarczonych przez pierścień kluczy. Nie oczekuje uprawnień na poziomie elementu, takich jak te udostępniane przez usługę Azure KeyVault do wymuszania dodatkowej izolacji. Próba uzyskania uprawnień na poziomie elementu powoduje wygenerowanie błędów aplikacji. Jeśli nie chcesz polegać na wbudowanej izolacji aplikacji, należy używać oddzielnych lokalizacji magazynu kluczy i nie udostępniać ich między aplikacjami.
Dyskryminujące aplikacje (ApplicationDiscriminator) umożliwiają różnym aplikacjom współużytkowanie tego samego materiału klucza głównego, ale przechowywanie ich ładunków kryptograficznych różni się od siebie. Aby aplikacje mogły odczytywać ze sobą ładunki kryptograficzne, muszą mieć tę samą dyskryminującą aplikację, którą można ustawić przez wywołanie metody
SetApplicationName
.W przypadku naruszenia zabezpieczeń aplikacji (na przykład ataku RCE) wszystkie materiały klucza głównego dostępne dla tej aplikacji muszą być również uznawane za naruszone, niezależnie od stanu ochronyrest . Oznacza to, że jeśli dwa aplikacje są wskazywane na to samo repozytorium, nawet jeśli korzystają z różnych dyskryminujących aplikacji, kompromis jednego z nich jest funkcjonalnie równoważny z naruszeniem obu tych elementów.
Ta klauzula "funkcjonalnie równoważna naruszeniu obu" jest przechowywana nawet wtedy, gdy obie aplikacje używają różnych mechanizmów ochrony kluczy w lokalizacji rest. Zazwyczaj nie jest to oczekiwana konfiguracja. Mechanizm ochrony na poziomierest jest przeznaczony do zapewnienia ochrony w przypadku, gdy cyberatak uzyskuje dostęp do odczytu do repozytorium. Cyberattacker, który uzyskuje dostęp do zapisu do repozytorium (być może dlatego, że uzyskał uprawnienia do wykonywania kodu w aplikacji), może wstawić złośliwe klucze do magazynu. System ochrony danych celowo nie zapewnia ochrony przed cyberatakiem, który uzyskuje dostęp do zapisu w repozytorium kluczy.
Jeśli aplikacje muszą pozostać naprawdę odizolowane od siebie, powinny używać różnych repozytoriów kluczy. To naturalnie wypada z definicji "izolowanej". Aplikacje nie są izolowane, jeśli wszystkie mają dostęp do odczytu i zapisu do magazynów danych.
Zmienianie algorytmów przy użyciu metody UseCryptographicAlgorithms
Stos ochrony danych umożliwia zmianę domyślnego algorytmu używanego przez nowo wygenerowane klucze. Najprostszym sposobem wykonania tej czynności jest wywołanie z wywołania UseCryptographicAlgorithms zwrotnego konfiguracji:
builder.Services.AddDataProtection()
.UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
Wartość domyślna EncryptionAlgorithm to AES-256-CBC, a domyślna wartość ValidationAlgorithm to HMACSHA256. Zasady domyślne mogą być ustawiane przez administratora systemu za pośrednictwem zasad dla całej maszyny, ale jawne wywołanie UseCryptographicAlgorithms
zastąpi domyślne zasady.
Wywołanie UseCryptographicAlgorithms
umożliwia określenie żądanego algorytmu ze wstępnie zdefiniowanej wbudowanej listy. Nie musisz martwić się o implementację algorytmu. W powyższym scenariuszu system ochrony danych próbuje użyć implementacji CNG AES, jeśli jest uruchomiona w systemie Windows. W przeciwnym razie wraca do klasy zarządzanej System.Security.Cryptography.Aes .
Implementację można określić ręcznie za pomocą wywołania metody UseCustomCryptographicAlgorithms.
Napiwek
Zmiana algorytmów nie ma wpływu na istniejące klucze w pierścieniu kluczy. Dotyczy tylko nowo wygenerowanych kluczy.
Określanie niestandardowych algorytmów zarządzanych
Aby określić niestandardowe algorytmy zarządzane, utwórz ManagedAuthenticatedEncryptorConfiguration wystąpienie wskazujące typy implementacji:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Ogólnie rzecz biorąc właściwości *Type muszą wskazywać konkretne, wystąpienia (za pośrednictwem publicznego ctor bez parametrów) implementacji SymmetricAlgorithm i KeyedHashAlgorithm, choć system specjalne przypadki niektórych wartości, takich jak typeof(Aes)
dla wygody.
Uwaga
SymmetricAlgorithm musi mieć długość klucza ≥ 128 bitów i rozmiar bloku ≥ 64 bitów i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. KluczedHashAlgorithm musi mieć rozmiar skrótu >= 128 bitów i musi obsługiwać klucze długości równej długości skrótu algorytmu skrótu. KeyedHashAlgorithm nie jest ściśle wymagany do bycia HMAC.
Określanie niestandardowych algorytmów CNG systemu Windows
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania WBC w trybie HMAC, utwórz CngCbcAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar >bloku = 64 bity i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm skrótu musi mieć rozmiar skrótu >= 128 bitów i musi obsługiwać otwieranie za pomocą flagi BCRYPT_ALG_HANDLE_HMAC_FLAG. *Właściwości dostawcy można ustawić na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania Galois/Counter Mode z walidacją, utwórz CngGcmAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar bloku o dokładnie 128 bitach i musi obsługiwać szyfrowanie GCM. Właściwość można ustawić EncryptionAlgorithmProvider na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Określanie innych algorytmów niestandardowych
Mimo że system ochrony danych nie jest uwidaczniony jako interfejs API pierwszej klasy, jest wystarczająco rozszerzalny, aby umożliwić określenie niemal dowolnego rodzaju algorytmu. Na przykład można zachować wszystkie klucze zawarte w sprzętowym module zabezpieczeń (HSM) i zapewnić niestandardową implementację procedur szyfrowania i odszyfrowywania rdzeni. Aby uzyskać więcej informacji, zobacz IAuthenticatedEncryptor w temacie Rozszerzalność kryptografii podstawowej.
Utrwalanie kluczy podczas hostowania w kontenerze platformy Docker
W przypadku hostowania w kontenerze platformy Docker klucze powinny być przechowywane w następujących elementach:
- Folder, który jest woluminem platformy Docker, który utrzymuje się poza okresem istnienia kontenera, na przykład woluminem udostępnionym lub woluminem zainstalowanym na hoście.
- Dostawca zewnętrzny, taki jak Azure Blob Storage (pokazany
ProtectKeysWithAzureKeyVault
w sekcji) lub Redis.
Utrwalanie kluczy za pomocą usługi Redis
Do przechowywania kluczy powinny być używane tylko wersje usługi Redis obsługujące trwałość danych Redis. Usługa Azure Blob Storage jest trwała i może służyć do przechowywania kluczy. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Rejestrowanie ochrony danych
Włącz Information
rejestrowanie na poziomie funkcji DataProtection, aby pomóc w diagnozowaniu problemu. appsettings.json
Następujący plik umożliwia rejestrowanie informacji interfejsu API ochrony danych:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.DataProtection": "Information"
}
},
"AllowedHosts": "*"
}
Aby uzyskać więcej informacji na temat rejestrowania, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core.
Dodatkowe zasoby
Gdy system ochrony danych jest inicjowany, stosuje ustawienia domyślne na podstawie środowiska operacyjnego. Te ustawienia są odpowiednie dla aplikacji działających na jednej maszynie. Istnieją jednak przypadki, w których deweloper może chcieć zmienić ustawienia domyślne:
- Aplikacja jest rozłożona na wiele maszyn.
- Ze względów zgodności.
W tych scenariuszach system ochrony danych oferuje zaawansowany interfejs API konfiguracji.
Ostrzeżenie
Podobnie jak w przypadku plików konfiguracji pierścień kluczy ochrony danych powinien być chroniony przy użyciu odpowiednich uprawnień. Możesz wybrać szyfrowanie kluczy w witrynie rest, ale nie uniemożliwia to cyberatakom tworzenia nowych kluczy. W związku z tym ma to wpływ na bezpieczeństwo aplikacji. Lokalizacja magazynu skonfigurowana przy użyciu usługi Data Protection powinna mieć ograniczony dostęp do samej aplikacji, podobnie jak w przypadku ochrony plików konfiguracji. Jeśli na przykład zdecydujesz się przechowywać pierścień kluczy na dysku, użyj uprawnień systemu plików. Upewnij się, że tylko identity w obszarze, w którym działa aplikacja internetowa, ma dostęp do odczytu, zapisu i tworzenia dostępu do tego katalogu. Jeśli używasz usługi Azure Blob Storage, tylko aplikacja internetowa powinna mieć możliwość odczytu, zapisu lub tworzenia nowych wpisów w magazynie obiektów blob itp.
Metoda rozszerzenia zwraca wartość AddDataProtection IDataProtectionBuilder. IDataProtectionBuilder
Uwidacznia metody rozszerzeń, które można połączyć w celu skonfigurowania opcji ochrony danych.
Następujące pakiety NuGet są wymagane dla rozszerzeń ochrony danych używanych w tym artykule:
ProtectKeysWithAzureKeyVault
Zaloguj się do platformy Azure przy użyciu interfejsu wiersza polecenia, na przykład:
az login
Aby przechowywać klucze w usłudze Azure Key Vault, skonfiguruj system ProtectKeysWithAzureKeyVault w Startup
klasie . blobUriWithSasToken
to pełny identyfikator URI, w którym powinien być przechowywany plik klucza. Identyfikator URI musi zawierać token SAS jako parametr ciągu zapytania:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
.ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());
}
Aby aplikacja komunikowała się i autoryzować się za pomocą usługi KeyVault, należy dodać pakiet platformy Azure.Identity
Ustaw lokalizację przechowywania pierścienia kluczy (na przykład PersistKeysToAzureBlobStorage). Lokalizacja musi być ustawiona, ponieważ wywołanie ProtectKeysWithAzureKeyVault
implementuje IXmlEncryptor funkcję , która wyłącza ustawienia automatycznej ochrony danych, w tym lokalizację przechowywania pierścienia kluczy. W poprzednim przykładzie użyto usługi Azure Blob Storage do utrwalania pierścienia kluczy. Aby uzyskać więcej informacji, zobacz Dostawcy magazynu kluczy: Azure Storage. Możesz również utrwalać pierścień kluczy lokalnie za pomocą funkcji PersistKeysToFileSystem.
Jest keyIdentifier
to identyfikator klucza magazynu kluczy używany do szyfrowania kluczy. Na przykład klucz utworzony w magazynie kluczy o nazwie dataprotection
w obiekcie contosokeyvault
ma identyfikator https://contosokeyvault.vault.azure.net/keys/dataprotection/
klucza . Podaj aplikację z uprawnieniami Pobierz, Odpakuj klucz i Zawij klucz do magazynu kluczy.
ProtectKeysWithAzureKeyVault
Przeciążenia:
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, Uri, TokenCredential) umożliwia użycie identyfikatora URI keyIdentifier i tokenCredential, aby umożliwić systemowi ochrony danych korzystanie z magazynu kluczy.
- ProtectKeysWithAzureKeyVault(IDataProtectionBuilder, String, IKeyEncryptionKeyResolver) umożliwia korzystanie z ciągu keyIdentifier i IKeyEncryptionKeyResolver, aby umożliwić systemowi ochrony danych korzystanie z magazynu kluczy.
Jeśli aplikacja korzysta ze starszych pakietów platformy Azure (Microsoft.AspNetCore.DataProtection.AzureStorage i Microsoft.AspNetCore.DataProtection.AzureKeyVault), zalecamy usunięcie tych odwołań i uaktualnienie do plików Azure.Extensions.AspNetCore.DataProtection.Blobs i Azure.Extensions.AspNetCore.DataProtection.Keys. Te pakiety to miejsce, w którym są udostępniane nowe aktualizacje, oraz rozwiązywanie niektórych kluczowych problemów z zabezpieczeniami i stabilnością starszych pakietów.
services.AddDataProtection()
//This blob must already exist before the application is run
.PersistKeysToAzureBlobStorage("<storage account connection string", "<key store container name>", "<key store blob name>")
//Removing this line below for an initial run will ensure the file is created correctly
.ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());
PersistKeysToFileSystem
Aby przechowywać klucze w udziale UNC zamiast w domyślnej lokalizacji %LOCALAPPDATA% , skonfiguruj system za pomocą polecenia PersistKeysToFileSystem:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}
Ostrzeżenie
Jeśli zmienisz lokalizację trwałości klucza, system nie będzie już automatycznie szyfrować kluczy w restlokalizacji , ponieważ nie wie, czy dpAPI jest odpowiednim mechanizmem szyfrowania.
PersistKeysToDbContext
Aby przechowywać klucze w bazie danych przy użyciu elementu EntityFramework, skonfiguruj system przy użyciu pakietu Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToDbContext<DbContext>()
}
Powyższy kod przechowuje klucze w skonfigurowanej bazie danych. Używany kontekst bazy danych musi implementować IDataProtectionKeyContext
element . IDataProtectionKeyContext
uwidacznia właściwość DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
Ta właściwość reprezentuje tabelę, w której są przechowywane klucze. Utwórz tabelę ręcznie lub za pomocą DbContext
funkcji Migracje. Aby uzyskać więcej informacji, zobacz DataProtectionKey.
ProtectKeysWith*
System można skonfigurować tak, aby chronił klucze, rest wywołując dowolny z interfejsów API konfiguracji ProtectKeysWith* . Rozważmy poniższy przykład, który przechowuje klucze w udziale UNC i szyfruje te klucze przy rest użyciu określonego certyfikatu X.509:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}
Możesz podać element X509Certificate2 do ProtectKeysWithCertificateelementu , taki jak certyfikat załadowany z pliku:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}
Więcej przykładów i omówienie wbudowanych mechanizmów szyfrowania kluczy można znaleźć w temacie Szyfrowanie kluczy at Rest .
UnprotectKeysWithAnyCertificate
Certyfikaty i klucze rest odszyfrowywania można wymieniać przy użyciu tablicy certyfikatów X509Certificate2 za UnprotectKeysWithAnyCertificatepomocą polecenia :
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}
SetDefaultKeyLifetime
Aby skonfigurować system do używania okresu istnienia klucza 14 dni zamiast domyślnego 90 dni, użyj polecenia SetDefaultKeyLifetime:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
SetApplicationName
Domyślnie system ochrony danych izoluje aplikacje od siebie na podstawie ścieżek głównych zawartości, nawet jeśli współużytkują to samo repozytorium kluczy fizycznych. Ta izolacja uniemożliwia aplikacjom zrozumienie ładunków chronionych przez siebie.
Aby udostępnić chronione ładunki między aplikacjami:
- Skonfiguruj SetApplicationName w każdej aplikacji tę samą wartość.
- Użyj tej samej wersji stosu interfejsu API ochrony danych w aplikacjach. Wykonaj jedną z następujących czynności w plikach projektu aplikacji:
- Odwołuj się do tej samej wersji platformy udostępnionej za pośrednictwem Microsoft.AspNetCore.App metapakiet.
- Odwołuje się do tej samej wersji pakietu usługi Data Protection.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("shared app name");
}
SetApplicationName program wewnętrznie ustawia wartość DataProtectionOptions.ApplicationDiscriminator. Aby uzyskać więcej informacji na temat sposobu użycia dyskryminującego, zobacz następujące sekcje w dalszej części tego artykułu:
DisableAutomaticKeyGeneration
Może istnieć scenariusz, w którym nie chcesz, aby aplikacja automatycznie rzutować klucze (tworzyć nowe klucze) w miarę zbliżania się do wygaśnięcia. Jednym z przykładów tego scenariusza mogą być aplikacje skonfigurowane w relacji podstawowej/pomocniczej, gdzie tylko podstawowa aplikacja jest odpowiedzialna za kluczowe problemy z zarządzaniem, a aplikacje pomocnicze mają po prostu widok pierścienia kluczy tylko do odczytu. Aplikacje pomocnicze można skonfigurować tak, aby traktować pierścień kluczy jako tylko do odczytu, konfigurując system przy użyciu polecenia DisableAutomaticKeyGeneration:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.DisableAutomaticKeyGeneration();
}
Izolacja dla aplikacji
Gdy system ochrony danych jest dostarczany przez hosta ASP.NET Core, automatycznie izoluje aplikacje od siebie, nawet jeśli te aplikacje są uruchomione na tym samym koncie procesu roboczego i używają tego samego głównego materiału kluczy. Jest to podobne do modyfikatora IsolateApps z elementu System.Web <machineKey>
.
Mechanizm izolacji działa, biorąc pod uwagę każdą aplikację na komputerze lokalnym jako unikatową dzierżawę, w związku z czym IDataProtector rooted dla danej aplikacji automatycznie uwzględnia identyfikator aplikacji jako dyskryminujący (ApplicationDiscriminator). Unikatowy identyfikator aplikacji to ścieżka fizyczna aplikacji:
- W przypadku aplikacji hostowanych w usługach IIS unikatowy identyfikator to ścieżka fizyczna usług IIS aplikacji. Jeśli aplikacja jest wdrażana w środowisku farmy sieci Web, ta wartość jest stabilna przy założeniu, że środowiska usług IIS są podobnie skonfigurowane na wszystkich maszynach w farmie sieci Web.
- W przypadku aplikacji hostowanych samodzielnie na Kestrel serwerze unikatowy identyfikator to ścieżka fizyczna do aplikacji na dysku.
Unikatowy identyfikator jest przeznaczony do przetrwania resetowania — zarówno pojedynczej aplikacji, jak i samej maszyny.
Ten mechanizm izolacji zakłada, że aplikacje nie są złośliwe. Złośliwa aplikacja zawsze może mieć wpływ na dowolną inną aplikację działającą na tym samym koncie procesu roboczego. W udostępnionym środowisku hostingu, w którym aplikacje są wzajemnie niezaufane, dostawca hostingu powinien podjąć kroki w celu zapewnienia izolacji na poziomie systemu operacyjnego między aplikacjami, w tym oddzielenia bazowych repozytoriów kluczy aplikacji.
Jeśli system ochrony danych nie jest udostępniany przez hosta platformy ASP.NET Core (na przykład w przypadku utworzenia wystąpienia za pośrednictwem konkretnego DataProtectionProvider
typu) izolacja aplikacji jest domyślnie wyłączona. Gdy izolacja aplikacji jest wyłączona, wszystkie aplikacje wspierane przez ten sam materiał kluczy mogą współdzielić ładunki, o ile zapewniają odpowiednie cele. Aby zapewnić izolację aplikacji w tym środowisku, wywołaj metodę SetApplicationName w obiekcie konfiguracji i podaj unikatową nazwę dla każdej aplikacji.
Ochrona danych i izolacja aplikacji
Rozważ następujące kwestie dotyczące izolacji aplikacji:
Gdy wiele aplikacji jest wskazywanych na to samo repozytorium kluczy, intencją jest to, że aplikacje współużytkują ten sam materiał klucza głównego. Ochrona danych jest opracowywana przy założeniu, że wszystkie aplikacje współużytkujące pierścień kluczy mogą uzyskiwać dostęp do wszystkich elementów w tym pierścieniu kluczy. Unikatowy identyfikator aplikacji służy do izolowania kluczy specyficznych dla aplikacji pochodzących z kluczy dostarczonych przez pierścień kluczy. Nie oczekuje uprawnień na poziomie elementu, takich jak te udostępniane przez usługę Azure KeyVault do wymuszania dodatkowej izolacji. Próba uzyskania uprawnień na poziomie elementu powoduje wygenerowanie błędów aplikacji. Jeśli nie chcesz polegać na wbudowanej izolacji aplikacji, należy używać oddzielnych lokalizacji magazynu kluczy i nie udostępniać ich między aplikacjami.
Dyskryminujące aplikacje (ApplicationDiscriminator) umożliwiają różnym aplikacjom współużytkowanie tego samego materiału klucza głównego, ale przechowywanie ich ładunków kryptograficznych różni się od siebie. Aby aplikacje mogły odczytywać ze sobą ładunki kryptograficzne, muszą mieć tę samą dyskryminującą aplikację, którą można ustawić przez wywołanie metody
SetApplicationName
.W przypadku naruszenia zabezpieczeń aplikacji (na przykład ataku RCE) wszystkie materiały klucza głównego dostępne dla tej aplikacji muszą być również uznawane za naruszone, niezależnie od stanu ochronyrest . Oznacza to, że jeśli dwa aplikacje są wskazywane na to samo repozytorium, nawet jeśli korzystają z różnych dyskryminujących aplikacji, kompromis jednego z nich jest funkcjonalnie równoważny z naruszeniem obu tych elementów.
Ta klauzula "funkcjonalnie równoważna naruszeniu obu" jest przechowywana nawet wtedy, gdy obie aplikacje używają różnych mechanizmów ochrony kluczy w lokalizacji rest. Zazwyczaj nie jest to oczekiwana konfiguracja. Mechanizm ochrony na poziomierest jest przeznaczony do zapewnienia ochrony w przypadku, gdy cyberatak uzyskuje dostęp do odczytu do repozytorium. Cyberattacker, który uzyskuje dostęp do zapisu do repozytorium (być może dlatego, że uzyskał uprawnienia do wykonywania kodu w aplikacji), może wstawić złośliwe klucze do magazynu. System ochrony danych celowo nie zapewnia ochrony przed cyberatakiem, który uzyskuje dostęp do zapisu w repozytorium kluczy.
Jeśli aplikacje muszą pozostać naprawdę odizolowane od siebie, powinny używać różnych repozytoriów kluczy. To naturalnie wypada z definicji "izolowanej". Aplikacje nie są izolowane, jeśli wszystkie mają dostęp do odczytu i zapisu do magazynów danych.
Zmienianie algorytmów przy użyciu metody UseCryptographicAlgorithms
Stos ochrony danych umożliwia zmianę domyślnego algorytmu używanego przez nowo wygenerowane klucze. Najprostszym sposobem wykonania tej czynności jest wywołanie z wywołania UseCryptographicAlgorithms zwrotnego konfiguracji:
services.AddDataProtection()
.UseCryptographicAlgorithms(
new AuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
Wartość domyślna EncryptionAlgorithm to AES-256-CBC, a domyślna wartość ValidationAlgorithm to HMACSHA256. Zasady domyślne mogą być ustawiane przez administratora systemu za pośrednictwem zasad dla całej maszyny, ale jawne wywołanie UseCryptographicAlgorithms
zastąpi domyślne zasady.
Wywołanie UseCryptographicAlgorithms
umożliwia określenie żądanego algorytmu ze wstępnie zdefiniowanej wbudowanej listy. Nie musisz martwić się o implementację algorytmu. W powyższym scenariuszu system ochrony danych próbuje użyć implementacji CNG AES, jeśli jest uruchomiona w systemie Windows. W przeciwnym razie wraca do klasy zarządzanej System.Security.Cryptography.Aes .
Implementację można określić ręcznie za pomocą wywołania metody UseCustomCryptographicAlgorithms.
Napiwek
Zmiana algorytmów nie ma wpływu na istniejące klucze w pierścieniu kluczy. Dotyczy tylko nowo wygenerowanych kluczy.
Określanie niestandardowych algorytmów zarządzanych
Aby określić niestandardowe algorytmy zarządzane, utwórz ManagedAuthenticatedEncryptorConfiguration wystąpienie wskazujące typy implementacji:
serviceCollection.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new ManagedAuthenticatedEncryptorConfiguration()
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Ogólnie rzecz biorąc właściwości *Type muszą wskazywać konkretne, wystąpienia (za pośrednictwem publicznego ctor bez parametrów) implementacji SymmetricAlgorithm i KeyedHashAlgorithm, choć system specjalne przypadki niektórych wartości, takich jak typeof(Aes)
dla wygody.
Uwaga
SymmetricAlgorithm musi mieć długość klucza ≥ 128 bitów i rozmiar bloku ≥ 64 bitów i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. KluczedHashAlgorithm musi mieć rozmiar skrótu >= 128 bitów i musi obsługiwać klucze długości równej długości skrótu algorytmu skrótu. KeyedHashAlgorithm nie jest ściśle wymagany do bycia HMAC.
Określanie niestandardowych algorytmów CNG systemu Windows
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania WBC w trybie HMAC, utwórz CngCbcAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngCbcAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar >bloku = 64 bity i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm skrótu musi mieć rozmiar skrótu >= 128 bitów i musi obsługiwać otwieranie za pomocą flagi BCRYPT_ALG_HANDLE_HMAC_FLAG. *Właściwości dostawcy można ustawić na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania Galois/Counter Mode z walidacją, utwórz CngGcmAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngGcmAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar bloku o dokładnie 128 bitach i musi obsługiwać szyfrowanie GCM. Właściwość można ustawić EncryptionAlgorithmProvider na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Określanie innych algorytmów niestandardowych
Mimo że system ochrony danych nie jest uwidaczniony jako interfejs API pierwszej klasy, jest wystarczająco rozszerzalny, aby umożliwić określenie niemal dowolnego rodzaju algorytmu. Na przykład można zachować wszystkie klucze zawarte w sprzętowym module zabezpieczeń (HSM) i zapewnić niestandardową implementację procedur szyfrowania i odszyfrowywania rdzeni. Aby uzyskać więcej informacji, zobacz IAuthenticatedEncryptor w temacie Rozszerzalność kryptografii podstawowej.
Utrwalanie kluczy podczas hostowania w kontenerze platformy Docker
W przypadku hostowania w kontenerze platformy Docker klucze powinny być przechowywane w następujących elementach:
- Folder, który jest woluminem platformy Docker, który utrzymuje się poza okresem istnienia kontenera, na przykład woluminem udostępnionym lub woluminem zainstalowanym na hoście.
- Dostawca zewnętrzny, taki jak Azure Blob Storage (pokazany
ProtectKeysWithAzureKeyVault
w sekcji) lub Redis.
Utrwalanie kluczy za pomocą usługi Redis
Do przechowywania kluczy powinny być używane tylko wersje usługi Redis obsługujące trwałość danych Redis. Usługa Azure Blob Storage jest trwała i może służyć do przechowywania kluczy. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Rejestrowanie ochrony danych
Włącz Information
rejestrowanie na poziomie funkcji DataProtection, aby pomóc w diagnozowaniu problemu. appsettings.json
Następujący plik umożliwia rejestrowanie informacji interfejsu API ochrony danych:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.DataProtection": "Information"
}
}
}
Aby uzyskać więcej informacji na temat rejestrowania, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core.