使用 ASP.NET Core 安全地存储开发中的应用机密
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文的 .NET 9 版本。
作者:Rick Anderson 和 Kirk Larkin
本文介绍如何在开发计算机上管理 ASP.NET Core 应用的敏感数据。 切勿将密码或其他敏感数据存储在源代码或配置文件中。 不得将生产机密用于开发或测试。 机密不得随应用一起部署。 应通过受控方式(如 Azure 密钥库)访问生产机密。 Azure 测试和生产机密可以使用 Azure 密钥库配置提供程序进行存储和保护。
有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流。
要在 .NET 控制台应用中使用用户机密,请参阅此 GitHub 问题。
环境变量
环境变量用于避免在代码或本地配置文件中存储应用机密。 环境变量会替代之前指定的所有配置源的配置值。
请考虑使用 ASP.NET Core Web 应用,其中已启用“个人用户帐户”安全性。 默认数据库连接字符串包含在项目的 appsettings.json
文件中,并包含密钥 DefaultConnection
。 默认连接字符串适用于 LocalDB,它在用户模式下运行,不需要密码。 在应用部署期间,可使用环境变量的值替代 DefaultConnection
键值。 环境变量可能会存储具有敏感凭据的完整连接字符串。
警告
环境变量通常以未加密纯文本的形式进行存储。 如果计算机或进程遭到入侵,那么不受信任方可访问环境变量。 可能需要采取其他措施来防止泄露用户机密。
所有平台上的环境变量分层键都不支持 :
分隔符。 例如,Bash 不支持 :
分隔符。 双下划线 __
是:
- 受所有平台支持。
- 自动替换为冒号,
:
。
机密管理器
机密管理器工具存储应用程序开发期间的敏感数据。 在此上下文中,一段敏感数据是应用机密。 应用机密存储在与项目树不同的位置。 应用机密与特定项目关联,或者跨多个项目共享。 应用机密不会签入到源代码管理中。
警告
机密管理器工具不会加密存储的机密,不得被视为受信任的存储。 它仅用于开发。 密钥和值存储在用户配置文件目录中的 JSON 配置文件中。
机密管理器工具的工作原理
机密管理器工具会隐藏实现详细信息,例如值的存储位置和存储方法。 可在不知道这些实现详细信息的情况下使用该工具。 这些值存储在本地计算机的用户配置文件文件夹中的 JSON 文件中:
文件系统路径:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
在上述文件路径中,将 <user_secrets_id>
替换为在项目文件中指定的 UserSecretsId
值。
不要编写依赖于使用机密管理器工具保存的数据的位置或格式的代码。 这些实现详细信息可能有变。 例如,机密值不会加密。
启用机密存储
机密管理器工具会对用户配置文件中存储的特定于项目的配置设置进行操作。
使用 CLI
机密管理器工具包含一个 init
命令。 若要使用用户机密,请在项目目录中运行以下命令:
dotnet user-secrets init
上述命令会将 UserSecretsId
元素添加到项目文件的 PropertyGroup
中。 默认情况下,UserSecretsId
的内部文本是 GUID。 内部文本是任意的,但对于项目来说是唯一的。
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>
使用 Visual Studio
在 Visual Studio 中,在解决方案资源管理器中右键单击该项目,然后从上下文菜单中选择“管理用户机密”。 该手势会将 UserSecretsId
元素(填充有 GUID)添加到项目文件中。
如果 GenerateAssemblyInfo
为 false
如果禁用了程序集信息属性的生成,请手动在 AssemblyInfo.cs
中添加 UserSecretsIdAttribute。 例如:
[assembly: UserSecretsId("your_user_secrets_id")]
手动将 UserSecretsId
属性添加到 AssemblyInfo.cs
时,UserSecretsId
值必须与项目文件中的值匹配。
设置机密
定义由键和值组成的应用机密。 机密与项目的 UserSecretsId
值相关联。 例如,从项目文件所在的目录中运行以下命令:
dotnet user-secrets set "Movies:ServiceApiKey" "12345"
在上述示例中,冒号表示 Movies
是具有 ServiceApiKey
属性的对象文字。
也可从其他目录使用机密管理器工具。 使用 --project
选项提供项目文件所在的文件系统路径。 例如:
dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"
Visual Studio 中的 JSON 结构平展
Visual Studio 的管理用户机密手势会在文本编辑器中打开secrets.json
文件。 将secrets.json
的内容替换为要存储的键/值对。 例如:
{
"Movies": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"ServiceApiKey": "12345"
}
}
通过 dotnet user-secrets remove
或 dotnet user-secrets set
进行修改后,平展 JSON 结构。 例如,运行 dotnet user-secrets remove "Movies:ConnectionString"
会折叠 Movies
对象文字。 修改后的文件类似于以下 JSON:
{
"Movies:ServiceApiKey": "12345"
}
设置多个机密
可通过管道将 JSON 传递给 set
命令来设置一批机密。 在下面的示例中,将input.json
文件的内容通过管道传递给set
命令。
打开命令行界面,然后执行以下命令:
type .\input.json | dotnet user-secrets set
访问机密
若要访问机密,请完成以下步骤:
注册用户机密配置源
用户机密配置提供程序 会向 .NET 配置 API 注册适当的配置源。
通过 dotnet new 或 Visual Studio 创建的 ASP.NET Core Web 应用会生成以下代码:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.CreateBuilder 使用预配置的默认值初始化 WebApplicationBuilder 类的新实例。 当 EnvironmentName 是 Development 时,初始化的 WebApplicationBuilder
(builder
) 会提供默认配置并调用 AddUserSecrets:
通过配置 API 读取机密
请考虑以下读取 Movies:ServiceApiKey
键的示例:
Program.cs 文件:
var builder = WebApplication.CreateBuilder(args);
var movieApiKey = builder.Configuration["Movies:ServiceApiKey"];
var app = builder.Build();
app.MapGet("/", () => movieApiKey);
app.Run();
RazorPages 页面模型:
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public void OnGet()
{
var moviesApiKey = _config["Movies:ServiceApiKey"];
// call Movies service with the API key
}
}
有关详细信息,请参阅 ASP.NET Core 中的配置。
将机密映射到 POCO
对于聚合相关属性来说,将整个对象文字映射到 POCO(具有属性的简单 .NET 类)很有用。
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
若要将上述机密映射到 POCO,请使用 .NET 配置 API 的对象图绑定功能。 下面的代码绑定到自定义 MovieSettings
POCO 并访问 ServiceApiKey
属性值:
var moviesConfig =
Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;
Movies:ConnectionString
和 Movies:ServiceApiKey
机密映射到 MovieSettings
中的相应属性:
public class MovieSettings
{
public string ConnectionString { get; set; }
public string ServiceApiKey { get; set; }
}
用机密替换字符串
以纯文本形式存储密码不太安全。 从不将机密存储在配置文件中,例如 appsettings.json
,可能会签入源代码存储库。
例如,存储在其中appsettings.json
的数据库连接字符串不应包含密码。 而是将密码存储为机密,并在运行时将密码包含在连接字符串中。 例如:
dotnet user-secrets set "DbPassword" "`<secret value>`"
将 <secret value>
前面的示例中的占位符替换为密码值。 在对象的Password属性上SqlConnectionStringBuilder设置机密的值,将其作为密码值包含在连接字符串中:
using System.Data.SqlClient;
var builder = WebApplication.CreateBuilder(args);
var conStrBuilder = new SqlConnectionStringBuilder(
builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;
var app = builder.Build();
app.MapGet("/", () => connection);
app.Run();
列出机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets list
随即显示以下输出:
Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345
在前面的示例中,键名称中的冒号表示secrets.json
中的对象层次结构。
删除单个机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets remove "Movies:ConnectionString"
已修改应用的secrets.json
文件以删除与Movies:ConnectionString
键关联的键值对:
{
"Movies": {
"ServiceApiKey": "12345"
}
}
dotnet user-secrets list
显示以下消息:
Movies:ServiceApiKey = 12345
删除所有机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets clear
已从secrets.json
文件中删除应用的所有用户机密:
{}
运行 dotnet user-secrets list
将显示以下消息:
No secrets configured for this application.
使用 Visual Studio 管理用户机密
若要在 Visual Studio 中管理用户机密,请在解决方案资源管理器中右键单击该项目,然后选择“管理用户机密”:
将用户机密从 ASP.NET Framework 迁移到 ASP.NET Core
请参阅此 GitHub 问题。
非 Web 应用程序中的用户机密
面向 Microsoft.NET.Sdk.Web
的项目会自动包括对用户机密的支持。 对于面向 Microsoft.NET.Sdk
(例如控制台应用程序)的项目,请显式安装配置扩展和用户机密 NuGet 包。
使用 PowerShell:
Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets
使用 .NET CLI:
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
安装包后,请初始化项目并使用与 Web 应用相同的方式设置机密。 以下示例显示了一个控制台应用程序,该应用程序检索使用密钥“AppSecret”设置的机密的值:
using Microsoft.Extensions.Configuration;
namespace ConsoleApp;
class Program
{
static void Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
Console.WriteLine(config["AppSecret"]);
}
}
其他资源
- 若要了解如何从 IIS 访问用户机密,请查看此问题和此问题。
- ASP.NET Core 中的配置
- ASP.NET Core 中的 Azure Key Vault 配置提供程序
作者:Rick Anderson、Kirk Larkin、Daniel Roth 和 Scott Addie
本文介绍如何在开发计算机上管理 ASP.NET Core 应用的敏感数据。 切勿将密码或其他敏感数据存储在源代码或配置文件中。 不得将生产机密用于开发或测试。 机密不得随应用一起部署。 应通过受控方式(如 Azure 密钥库)访问生产机密。 Azure 测试和生产机密可以使用 Azure 密钥库配置提供程序进行存储和保护。
有关测试和生产环境的身份验证的详细信息,请参阅 安全身份验证流。
环境变量
环境变量用于避免在代码或本地配置文件中存储应用机密。 环境变量会替代之前指定的所有配置源的配置值。
请考虑使用 ASP.NET Core Web 应用,其中已启用“个人用户帐户”安全性。 默认数据库连接字符串包含在项目的 appsettings.json
文件中,并包含密钥 DefaultConnection
。 默认连接字符串适用于 LocalDB,它在用户模式下运行,不需要密码。 在应用部署期间,可使用环境变量的值替代 DefaultConnection
键值。 环境变量可能会存储具有敏感凭据的完整连接字符串。
警告
环境变量通常以未加密纯文本的形式进行存储。 如果计算机或进程遭到入侵,那么不受信任方可访问环境变量。 可能需要采取其他措施来防止泄露用户机密。
所有平台上的环境变量分层键都不支持 :
分隔符。 例如,Bash 不支持 :
分隔符。 双下划线 __
是:
- 受所有平台支持。
- 自动替换为冒号,
:
。
机密管理器
机密管理器工具存储应用程序开发期间的敏感数据。 在此上下文中,一段敏感数据是应用机密。 应用机密存储在与项目树不同的位置。 应用机密与特定项目关联,或者跨多个项目共享。 应用机密不会签入到源代码管理中。
警告
机密管理器工具不会加密存储的机密,不得被视为受信任的存储。 它仅用于开发。 密钥和值存储在用户配置文件目录中的 JSON 配置文件中。
机密管理器工具的工作原理
机密管理器工具会隐藏实现详细信息,例如值的存储位置和存储方法。 可在不知道这些实现详细信息的情况下使用该工具。 这些值存储在本地计算机的用户配置文件文件夹中的 JSON 文件中:
文件系统路径:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
在上述文件路径中,将 <user_secrets_id>
替换为在项目文件中指定的 UserSecretsId
值。
不要编写依赖于使用机密管理器工具保存的数据的位置或格式的代码。 这些实现详细信息可能有变。 例如,机密值不会加密,但将来可能会加密。
启用机密存储
机密管理器工具会对用户配置文件中存储的特定于项目的配置设置进行操作。
在 .NET Core SDK 3.0.100 或更高版本中,机密管理器工具包含一个 init
命令。 若要使用用户机密,请在项目目录中运行以下命令:
dotnet user-secrets init
上述命令会将 UserSecretsId
元素添加到项目文件的 PropertyGroup
中。 默认情况下,UserSecretsId
的内部文本是 GUID。 内部文本是任意的,但对于项目来说是唯一的。
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>
在 Visual Studio 中,在解决方案资源管理器中右键单击该项目,然后从上下文菜单中选择“管理用户机密”。 该手势会将 UserSecretsId
元素(填充有 GUID)添加到项目文件中。
设置机密
定义由键和值组成的应用机密。 机密与项目的 UserSecretsId
值相关联。 例如,从项目文件所在的目录中运行以下命令:
dotnet user-secrets set "Movies:ServiceApiKey" "12345"
在上述示例中,冒号表示 Movies
是具有 ServiceApiKey
属性的对象文字。
也可从其他目录使用机密管理器工具。 使用 --project
选项提供项目文件所在的文件系统路径。 例如:
dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"
Visual Studio 中的 JSON 结构平展
Visual Studio 的管理用户机密手势会在文本编辑器中打开secrets.json
文件。 将secrets.json
的内容替换为要存储的键/值对。 例如:
{
"Movies": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"ServiceApiKey": "12345"
}
}
通过 dotnet user-secrets remove
或 dotnet user-secrets set
进行修改后,平展 JSON 结构。 例如,运行 dotnet user-secrets remove "Movies:ConnectionString"
会折叠 Movies
对象文字。 修改后的文件类似于以下 JSON:
{
"Movies:ServiceApiKey": "12345"
}
设置多个机密
可通过管道将 JSON 传递给 set
命令来设置一批机密。 在下面的示例中,将input.json
文件的内容通过管道传递给set
命令。
打开命令行界面,然后执行以下命令:
type .\input.json | dotnet user-secrets set
访问机密
若要访问机密,请完成以下步骤:
注册用户机密配置源
用户机密配置提供程序 会向 .NET 配置 API 注册适当的配置源。
当项目调用 CreateDefaultBuilder 时,用户机密配置源是在开发模式中自动添加的。 当 EnvironmentName 是 Development 时,CreateDefaultBuilder
会调用 AddUserSecrets:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
如果未调用 CreateDefaultBuilder
,则通过在 ConfigureAppConfiguration 中调用 AddUserSecrets 来显式添加用户机密配置源。 只有在开发环境中运行应用时才调用 AddUserSecrets
,如以下示例所示:
public class Program
{
public static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration((hostContext, builder) =>
{
// Add other providers for JSON, etc.
if (hostContext.HostingEnvironment.IsDevelopment())
{
builder.AddUserSecrets<Program>();
}
})
.Build();
host.Run();
}
}
通过配置 API 读取机密
如果注册了用户机密配置源,则 .NET 配置 API 可以读取机密。 构造函数注入可用于获取对 .NET 配置 API 的访问。 请考虑以下读取 Movies:ServiceApiKey
键的示例:
Startup 类:
public class Startup
{
private string _moviesApiKey = null;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
_moviesApiKey = Configuration["Movies:ServiceApiKey"];
}
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
await context.Response.WriteAsync($"Secret is {result}");
});
}
}
RazorPages 页面模型:
public class IndexModel : PageModel
{
private readonly IConfiguration _config;
public IndexModel(IConfiguration config)
{
_config = config;
}
public void OnGet()
{
var moviesApiKey = _config["Movies:ServiceApiKey"];
// call Movies service with the API key
}
}
有关详细信息,请参阅访问启动中的配置和访问Razor Pages中的配置。
将机密映射到 POCO
对于聚合相关属性来说,将整个对象文字映射到 POCO(具有属性的简单 .NET 类)很有用。
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
若要将上述机密映射到 POCO,请使用 .NET 配置 API 的对象图绑定功能。 下面的代码绑定到自定义 MovieSettings
POCO 并访问 ServiceApiKey
属性值:
var moviesConfig =
Configuration.GetSection("Movies").Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;
Movies:ConnectionString
和 Movies:ServiceApiKey
机密映射到 MovieSettings
中的相应属性:
public class MovieSettings
{
public string ConnectionString { get; set; }
public string ServiceApiKey { get; set; }
}
用机密替换字符串
以纯文本形式存储密码不太安全。 从不将机密存储在配置文件中,例如 appsettings.json
,可能会签入源代码存储库。
例如,存储在其中appsettings.json
的数据库连接字符串不应包含密码。 而是将密码存储为机密,并在运行时将密码包含在连接字符串中。 例如:
dotnet user-secrets set "DbPassword" "<secret value>"
将 <secret value>
前面的示例中的占位符替换为密码值。 在对象的Password属性上SqlConnectionStringBuilder设置机密的值,将其作为密码值包含在连接字符串中:
using System.Data.SqlClient;
var builder = WebApplication.CreateBuilder(args);
var conStrBuilder = new SqlConnectionStringBuilder(
builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;
var app = builder.Build();
app.MapGet("/", () => connection);
app.Run();
列出机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets list
随即显示以下输出:
Movies:ConnectionString = Server=(localdb)\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true
Movies:ServiceApiKey = 12345
在前面的示例中,键名称中的冒号表示secrets.json
中的对象层次结构。
删除单个机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets remove "Movies:ConnectionString"
已修改应用的secrets.json
文件以删除与MoviesConnectionString
键关联的键值对:
{
"Movies": {
"ServiceApiKey": "12345"
}
}
dotnet user-secrets list
显示以下消息:
Movies:ServiceApiKey = 12345
删除所有机密
假设应用的secrets.json
文件包含下面两个机密:
{
"Movies:ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true",
"Movies:ServiceApiKey": "12345"
}
从项目文件所在的目录中运行以下命令:
dotnet user-secrets clear
已从secrets.json
文件中删除应用的所有用户机密:
{}
运行 dotnet user-secrets list
将显示以下消息:
No secrets configured for this application.
使用 Visual Studio 管理用户机密
若要在 Visual Studio 中管理用户机密,请在解决方案资源管理器中右键单击该项目,然后选择“管理用户机密”:
将用户机密从 ASP.NET Framework 迁移到 ASP.NET Core
请参阅此 GitHub 问题。
非 Web 应用程序中的用户机密
面向 Microsoft.NET.Sdk.Web
的项目会自动包括对用户机密的支持。 对于面向 Microsoft.NET.Sdk
(例如控制台应用程序)的项目,请显式安装配置扩展和用户机密 NuGet 包。
使用 PowerShell:
Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets
使用 .NET CLI:
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
安装包后,请初始化项目并使用与 Web 应用相同的方式设置机密。 以下示例显示了一个控制台应用程序,该应用程序检索使用密钥“AppSecret”设置的机密的值:
using Microsoft.Extensions.Configuration;
namespace ConsoleApp;
class Program
{
static void Main(string[] args)
{
IConfigurationRoot config = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.Build();
Console.WriteLine(config["AppSecret"]);
}
}
其他资源
- 若要了解如何从 IIS 访问用户机密,请查看此问题和此问题。
- ASP.NET Core 中的配置
- ASP.NET Core 中的 Azure Key Vault 配置提供程序