- 通用
- 身份验证
- 授权
- 数据保护
- 机密管理
配置 ASP.NET Core数据保护
当数据保护系统已初始化时,它将基于操作环境应用默认设置。 这些设置通常适用于在一台计算机上运行的应用程序。 在某些情况下,开发人员可能想要更改默认设置:
- 应用程序分布在多台计算机上。
- 出于合规性原因。
在这些情况下,数据保护系统提供了丰富的配置 API。
警告
与配置文件类似,应使用适当的权限保护数据保护密钥环。 你可以选择对静态密钥加密,但这不会阻止攻击者创建新密钥。 因此,应用的安全将受到影响。 使用数据保护配置的存储位置应该将其访问权限限制为应用本身,这与保护配置文件的方式类似。 例如,如果选择将密钥环存储在磁盘上,请使用文件系统权限。 确保你的 web 应用在其下运行的标识具有对该目录的读取、写入和创建访问权限。 如果使用 Azure Blob 存储,则只有 web 应用应能够在 Blob 存储中读取、写入或创建新条目等。
扩展方法AddDataProtection返回IDataProtectionBuilder。 IDataProtectionBuilder
公开扩展方法,你可以将这些方法链接在一起来配置数据保护选项。
本文中使用的数据保护扩展插件需要以下 NuGet 包:
ProtectKeysWithAzureKeyVault
若要在Azure Key Vault中存储密钥,请在 Startup
类中配置ProtectKeysWithAzureKeyVault的系统:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>")) .ProtectKeysWithAzureKeyVault("<keyIdentifier>", "<clientId>", "<clientSecret>"); }
设置密钥环存储位置(例如, PersistKeysToAzureBlobStorage)。 必须设置位置,因为调用 ProtectKeysWithAzureKeyVault
实现了禁用自动数据保护设置的IXmlEncryptor ,包括密钥环存储位置。 前面的示例使用 Azure Blob 存储来持久保存密钥环。 有关详细信息,请参阅密钥存储提供程序: Azure 存储。 还可以通过PersistKeysToFileSystem将密钥环保存到本地。
keyIdentifier
是用于密钥加密的密钥保管库密钥标识符。 例如,在 contosokeyvault
中名为 dataprotection
的密钥保管库中创建的密钥具有密钥标识符 https://contosokeyvault.vault.azure.net/keys/dataprotection/
。 向应用提供对密钥保管库的解包密钥和包装密钥权限。
ProtectKeysWithAzureKeyVault
重载:
- ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,KeyVaultClient,String)允许使用KeyVaultClient使数据保护系统能够使用密钥保管库。
- ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,string,string,X509Certificate2)允许使用
ClientId
和X509Certificate使数据保护系统能够使用密钥保管库。 - ProtectKeysWithAzureKeyVault (IDataProtectionBuilder,string,string,string)允许使用
ClientId
和ClientSecret
使数据保护系统能够使用密钥保管库。
PersistKeysToFileSystem
若要将密钥存储在 UNC 共享上,而不是存储在 % LOCALAPPDATA% 默认位置,请使用PersistKeysToFileSystem配置系统:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\")); }
警告
如果更改密钥持久性位置,系统将不再自动加密静态密钥,因为它不知道 DPAPI 是否为适当的加密机制。
ProtectKeysWith*
可以通过调用ProtectKeysWith*配置 api,将系统配置为保护静态密钥。 请考虑以下示例,该示例将密钥存储在 UNC 共享上,并使用特定的 x.509 证书对静态密钥进行加密:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\")) .ProtectKeysWithCertificate("thumbprint"); }
在 ASP.NET Core 2.1 或更高版本中,你可以提供ProtectKeysWithCertificate的X509Certificate2 ,例如从文件中加载的证书:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\")) .ProtectKeysWithCertificate( new X509Certificate2("certificate.pfx", "password")); }
有关内置密钥加密机制的更多示例和讨论,请参阅静态密钥加密。
UnprotectKeysWithAnyCertificate
在 ASP.NET Core 2.1 或更高版本中,你可以使用UnprotectKeysWithAnyCertificate的X509Certificate2
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\")) .ProtectKeysWithCertificate( new X509Certificate2("certificate.pfx", "password")); .UnprotectKeysWithAnyCertificate( new X509Certificate2("certificate_old_1.pfx", "password_1"), new X509Certificate2("certificate_old_2.pfx", "password_2")); }
SetDefaultKeyLifetime
若要将系统配置为使用14天的密钥生存期而不是默认的90天,请使用SetDefaultKeyLifetime:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .SetDefaultKeyLifetime(TimeSpan.FromDays(14)); }
SetApplicationName
默认情况下,数据保护系统基于其内容根路径将应用彼此隔离,即使它们共享相同的物理密钥存储库。 这可防止应用了解彼此的受保护负载。
在应用之间共享受保护的负载:
- 用相同的值在每个应用中配置 SetApplicationName。
- 在应用程序中使用相同版本的数据保护 API 堆栈。 在应用的项目文件中执行以下任一操作:
- 通过AspNetCore 元包引用相同的共享框架版本。
- 引用相同的数据保护包版本。
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .SetApplicationName("shared app name"); }
DisableAutomaticKeyGeneration
您可能会遇到这样的情况:不希望应用程序在接近过期时自动滚动更新密钥(创建新的密钥)。 这种情况的一个示例可能是在主/辅助关系中设置的应用,其中只有主应用负责密钥管理问题,辅助应用只是具有密钥环的只读视图。 可以通过使用 DisableAutomaticKeyGeneration配置系统,将辅助应用配置为将密钥环视为只读:
public void ConfigureServices(IServiceCollection services) { services.AddDataProtection() .DisableAutomaticKeyGeneration(); }
每应用程序隔离
数据保护系统提供了 ASP.NET Core 主机,但它自动隔离了从另一个,应用程序,即使这些应用在相同的工作进程帐户下运行,并且使用相同的主密钥材料。 这有点类似于 IsolateApps 的 <machineKey>
元素中的修饰符。
隔离机制的工作原理是将本地计算机上的每个应用视为唯一的租户,因此,任何给定应用的根 IDataProtector 会自动将应用 ID 包含为鉴别器。 应用的唯一 ID 是应用的物理路径:
- 对于在 IIS 中托管的应用,唯一 ID 是应用的 IIS 物理路径。 如果在 web 场环境中部署了应用,则此值是稳定的,假定在 web 场中的所有计算机上配置了类似的 IIS 环境。
- 对于在Kestrel 服务器上运行的自承载应用程序,唯一 ID 是指向磁盘上的应用程序的物理路径。
唯一标识符的设计目的是在每个应用程序和计算机本身—重置。
此隔离机制假定应用不是恶意的。 恶意应用始终会影响在同一工作进程帐户下运行的任何其他应用。 在应用不受信任的共享主机环境中,托管提供商应采取措施来确保应用之间的操作系统级隔离,包括分离应用程序的底层密钥存储库。
如果由 ASP.NET Core 主机未提供数据保护系统 (例如,如果通过其实例化DataProtectionProvider
具体类型) 应用程序隔离在默认情况下处于禁用状态。 禁用应用隔离后,只要提供相应的用途,同一密钥材料支持的所有应用就可以共享有效负载。 若要在此环境中提供应用隔离,请对配置对象调用SetApplicationName方法,并为每个应用提供唯一的名称。
用 UseCryptographicAlgorithms 更改算法
数据保护堆栈允许您更改新生成的密钥使用的默认算法。 执行此操作的最简单方法是从配置回调调用UseCryptographicAlgorithms :
services.AddDataProtection() .UseCryptographicAlgorithms( new AuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 });
services.AddDataProtection() .UseCryptographicAlgorithms( new AuthenticatedEncryptionSettings() { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 });
默认 EncryptionAlgorithm 为 AES-256-CBC,默认 ValidationAlgorithm 为 HMACSHA256。 系统管理员可以通过计算机范围的策略设置默认策略,但对 UseCryptographicAlgorithms
的显式调用会替代默认策略。
通过调用 UseCryptographicAlgorithms
,可以从预定义的内置列表中指定所需的算法。 您无需担心算法的实现。 在上述方案中,如果在 Windows 上运行,数据保护系统将尝试使用 AES 的 CNG 实现。 否则,它会回退到托管的系统。
可以通过调用UseCustomCryptographicAlgorithms手动指定实现。
提示
更改算法不会影响密钥环中的现有密钥。 它仅影响新生成的键。
指定自定义托管算法
若要指定自定义托管算法,请创建一个指向实现类型的ManagedAuthenticatedEncryptorConfiguration实例:
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) });
若要指定自定义托管算法,请创建一个指向实现类型的ManagedAuthenticatedEncryptionSettings实例:
serviceCollection.AddDataProtection() .UseCustomCryptographicAlgorithms( new ManagedAuthenticatedEncryptionSettings() { // A type that subclasses SymmetricAlgorithm EncryptionAlgorithmType = typeof(Aes), // Specified in bits EncryptionAlgorithmKeySize = 256, // A type that subclasses KeyedHashAlgorithm ValidationAlgorithmType = typeof(HMACSHA256) });
通常,*类型属性必须指向system.security.cryptography.symmetricalgorithm和KeyedHashAlgorithm的具体实例实例(通过公共无参数的 ctor)实现,尽管系统特别适用于一些值(如 typeof(Aes)
)以方便使用。
备注
System.security.cryptography.symmetricalgorithm 必须具有≥128位的密钥长度和≥64位的块大小,并且必须支持 PKCS #7 填充的 CBC 模式加密。 KeyedHashAlgorithm 的摘要大小必须为 > = 128 位,并且它必须支持长度等于哈希算法摘要长度的键。 KeyedHashAlgorithm 不一定是 HMAC。
指定自定义 Windows CNG 算法
若要通过 HMAC 验证使用 CBC 模式加密指定自定义 Windows CNG 算法,请创建包含算法信息的CngCbcAuthenticatedEncryptorConfiguration实例:
services.AddDataProtection() .UseCustomCryptographicAlgorithms( new CngCbcAuthenticatedEncryptorConfiguration() { // Passed to BCryptOpenAlgorithmProvider EncryptionAlgorithm = "AES", EncryptionAlgorithmProvider = null, // Specified in bits EncryptionAlgorithmKeySize = 256, // Passed to BCryptOpenAlgorithmProvider HashAlgorithm = "SHA256", HashAlgorithmProvider = null });
若要通过 HMAC 验证使用 CBC 模式加密指定自定义 Windows CNG 算法,请创建包含算法信息的CngCbcAuthenticatedEncryptionSettings实例:
services.AddDataProtection() .UseCustomCryptographicAlgorithms( new CngCbcAuthenticatedEncryptionSettings() { // Passed to BCryptOpenAlgorithmProvider EncryptionAlgorithm = "AES", EncryptionAlgorithmProvider = null, // Specified in bits EncryptionAlgorithmKeySize = 256, // Passed to BCryptOpenAlgorithmProvider HashAlgorithm = "SHA256", HashAlgorithmProvider = null });
备注
对称块加密算法的密钥长度必须为 > = 128 位,块大小为 > = 64 位,并且它必须支持 PKCS #7 填充的 CBC 模式加密。 哈希算法的摘要大小必须为 > = 128 位,并且必须支持使用 BCRYPT_ALG_处理_HMAC_标志标志打开。 *提供程序属性可以设置为 null,以将默认提供程序用于指定的算法。 有关详细信息,请参阅BCryptOpenAlgorithmProvider文档。
若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的CngGcmAuthenticatedEncryptorConfiguration实例:
services.AddDataProtection() .UseCustomCryptographicAlgorithms( new CngGcmAuthenticatedEncryptorConfiguration() { // Passed to BCryptOpenAlgorithmProvider EncryptionAlgorithm = "AES", EncryptionAlgorithmProvider = null, // Specified in bits EncryptionAlgorithmKeySize = 256 });
若要使用 Galois/Counter 模式加密和验证来指定自定义 Windows CNG 算法,请创建包含算法信息的CngGcmAuthenticatedEncryptionSettings实例:
services.AddDataProtection() .UseCustomCryptographicAlgorithms( new CngGcmAuthenticatedEncryptionSettings() { // Passed to BCryptOpenAlgorithmProvider EncryptionAlgorithm = "AES", EncryptionAlgorithmProvider = null, // Specified in bits EncryptionAlgorithmKeySize = 256 });
备注
对称块密码算法的密钥长度必须为 > = 128 位,块大小正好为128位,并且必须支持 GCM 加密。 可以将EncryptionAlgorithmProvider属性设置为 null,以将默认提供程序用于指定的算法。 有关详细信息,请参阅BCryptOpenAlgorithmProvider文档。
指定其他自定义算法
尽管不是作为第一类 API 公开的,但数据保护系统的扩展能力足以允许指定几乎任何类型的算法。 例如,可以保留硬件安全模块(HSM)中包含的所有密钥,并提供核心加密和解密例程的自定义实现。 有关详细信息,请参阅核心加密扩展性中的IAuthenticatedEncryptor 。
在 Docker 容器中托管时保持密钥
在Docker容器中托管时,应在以下任一项中维护密钥:
- 一个文件夹,它是在容器的生存期之外保留的 Docker 卷,如共享卷或主机装入的卷。
- 外部提供程序,如Azure Key Vault或Redis。
通过 Redis 保持密钥
只应使用支持Redis 数据暂留的 Redis 版本来存储密钥。 Azure Blob 存储是持久性的,可用于存储密钥。 有关详细信息,请参阅此 GitHub 问题。