管理 Class 库的用户机密
Manage User Secrets for Class Library
情况
我有 3 个有问题的 dotnet 核心项目:
- 网络API
- 工人服务
- Class图书馆
在 class 库中,我有一个共享的 EmailService class,我在 Web API 和 Worker Service 中注册了依赖注入。
Web API 和 Worker Service 项目对我的 sendgrid API 键具有相同的配置部分,并且它们以完全相同的方式使用 IOptions 模式绑定到 POCO。它们都使用 AddScoped
方法注册。但 EmailService 的实际 class 实现在共享 class 库中。 运行 本地不会在 class 库(这可能有意义)以及 ETL 用户机密中获取我的用户机密。两个用户密码共享 json.
的相同精确值
问题
当我为 ETL 项目设置我的用户机密并在本地 运行 它们时,我的发送网格帐户的 API 密钥没有被提取,因为我认为, class 在 class 库中定义。
我试过的
我也尝试将相同的用户机密添加到 class 库中,但这似乎不起作用,我假设这是因为我的库中没有 appsettings.json class 图书馆,因为可能不应该有。
注意库不能有配置。即使它有一个 DLL 名称的配置文件 - 它也会被忽略。应用程序是那些可以并且应该具有配置的应用程序。两者中的每一个都可以有一个 EmailService 部分,将初始化一个配置 class (IOptions<T>
) 并注册到 DI 容器中。服务就是这样获取的,a
appsettings.config
{
"EmailService":
{
"somethingStatic": "abc:
}
}
appsettings.{Env}.config
{
"EmailService":
{
"apiKey": "xyz":
}
}
Startup.cs:
services.Configure<EmailServiceConfig>(context.Configuration.GetSection(EmailServiceConfig.SectionName));
EmailServiceConfig.cs
class EmailServiceConfig
{
public const string SectionName = nameof(EmailService);
public string SomethingStatic { get; set; }
public string ApiKey { get; set; }
}
EmailService.cs:
public EmailService(IOptions<EmailServiceConfig> config
{
}
这里的技巧是,在 3.1 中,工作人员服务没有 asp.net nuget 包,也没有明确引用 user-secret nuget 包,这有助于 user-secret 工作。但是在我引用 user-secrets nuget 包并将以下内容添加到 Program.cs 后,它开始工作:
首先,无需将用户机密添加到您的 class 库中,因为没有任何东西会提取这些机密。配置系统实际上并不关心您的 POCO 选项在哪个程序集中,特别是因为 Microsoft.Extensions.Configuration(这是加载用户机密的地方)仅 有点 与 Microsoft.Extensions.Options(这就是你的 POCO 的用途)。
由于您是通过选项模式使用配置的,只要依赖注入系统被配置为正确地提供配置选项的所有配置源,您库中的代码就不必太担心了。
因此,如果您对两个(正在执行的)程序集中的用户机密有疑问,那就是它们的配置方式。由于您有一个 ASP.NET 核心网络应用程序和一个辅助服务,我假设您正在为这两个项目使用主机构建器。在这种情况下,您不必太担心设置配置源,因为主机生成器带有一个合理的默认值,它确实包括开发模式下的用户机密。
无论如何,如果您遇到需要将用户机密配置为配置提供程序的情况,您应该知道 IConfigurationBuilder.AddUserSecrets
扩展方法通常希望您传入一个程序集,该程序集标识.csproj
文件中项目配置的用户机密。 – 如果您使用的是默认主机构建器,那么它会为您设置并使用您项目的程序集,这通常是您想要做的。
正如您自己发现的那样,an open bug for 3.1 可以防止用户机密直接用于 Worker 项目模板。原因是底层项目 SDK 忘记处理用于识别用户项目的 <UserSecretsId>
MSBuild 属性。
幸运的是,这个问题有一个简单的解决方法:您需要做的就是添加对 Microsoft.Extensions.Configuration.UserSecrets
包的显式引用。该包已被 Microsoft.Extensions.Hosting
隐式引用,默认情况下包含在 Worker 项目模板中,但通过再次显式添加它,您将启用一些神奇的 MSBuild 位,以使项目正确获取用户机密。
因此您的项目模板应如下所示:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>fb8be4c5-1316-42a7-8c30-3a752ed21c09</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.8" />
</ItemGroup>
</Project>
情况
我有 3 个有问题的 dotnet 核心项目:
- 网络API
- 工人服务
- Class图书馆
在 class 库中,我有一个共享的 EmailService class,我在 Web API 和 Worker Service 中注册了依赖注入。
Web API 和 Worker Service 项目对我的 sendgrid API 键具有相同的配置部分,并且它们以完全相同的方式使用 IOptions 模式绑定到 POCO。它们都使用 AddScoped
方法注册。但 EmailService 的实际 class 实现在共享 class 库中。 运行 本地不会在 class 库(这可能有意义)以及 ETL 用户机密中获取我的用户机密。两个用户密码共享 json.
问题
当我为 ETL 项目设置我的用户机密并在本地 运行 它们时,我的发送网格帐户的 API 密钥没有被提取,因为我认为, class 在 class 库中定义。
我试过的
我也尝试将相同的用户机密添加到 class 库中,但这似乎不起作用,我假设这是因为我的库中没有 appsettings.json class 图书馆,因为可能不应该有。
注意库不能有配置。即使它有一个 DLL 名称的配置文件 - 它也会被忽略。应用程序是那些可以并且应该具有配置的应用程序。两者中的每一个都可以有一个 EmailService 部分,将初始化一个配置 class (IOptions<T>
) 并注册到 DI 容器中。服务就是这样获取的,a
appsettings.config
{
"EmailService":
{
"somethingStatic": "abc:
}
}
appsettings.{Env}.config
{
"EmailService":
{
"apiKey": "xyz":
}
}
Startup.cs:
services.Configure<EmailServiceConfig>(context.Configuration.GetSection(EmailServiceConfig.SectionName));
EmailServiceConfig.cs
class EmailServiceConfig
{
public const string SectionName = nameof(EmailService);
public string SomethingStatic { get; set; }
public string ApiKey { get; set; }
}
EmailService.cs:
public EmailService(IOptions<EmailServiceConfig> config
{
}
这里的技巧是,在 3.1 中,工作人员服务没有 asp.net nuget 包,也没有明确引用 user-secret nuget 包,这有助于 user-secret 工作。但是在我引用 user-secrets nuget 包并将以下内容添加到 Program.cs 后,它开始工作:
首先,无需将用户机密添加到您的 class 库中,因为没有任何东西会提取这些机密。配置系统实际上并不关心您的 POCO 选项在哪个程序集中,特别是因为 Microsoft.Extensions.Configuration(这是加载用户机密的地方)仅 有点 与 Microsoft.Extensions.Options(这就是你的 POCO 的用途)。
由于您是通过选项模式使用配置的,只要依赖注入系统被配置为正确地提供配置选项的所有配置源,您库中的代码就不必太担心了。
因此,如果您对两个(正在执行的)程序集中的用户机密有疑问,那就是它们的配置方式。由于您有一个 ASP.NET 核心网络应用程序和一个辅助服务,我假设您正在为这两个项目使用主机构建器。在这种情况下,您不必太担心设置配置源,因为主机生成器带有一个合理的默认值,它确实包括开发模式下的用户机密。
无论如何,如果您遇到需要将用户机密配置为配置提供程序的情况,您应该知道 IConfigurationBuilder.AddUserSecrets
扩展方法通常希望您传入一个程序集,该程序集标识.csproj
文件中项目配置的用户机密。 – 如果您使用的是默认主机构建器,那么它会为您设置并使用您项目的程序集,这通常是您想要做的。
正如您自己发现的那样,an open bug for 3.1 可以防止用户机密直接用于 Worker 项目模板。原因是底层项目 SDK 忘记处理用于识别用户项目的 <UserSecretsId>
MSBuild 属性。
幸运的是,这个问题有一个简单的解决方法:您需要做的就是添加对 Microsoft.Extensions.Configuration.UserSecrets
包的显式引用。该包已被 Microsoft.Extensions.Hosting
隐式引用,默认情况下包含在 Worker 项目模板中,但通过再次显式添加它,您将启用一些神奇的 MSBuild 位,以使项目正确获取用户机密。
因此您的项目模板应如下所示:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>fb8be4c5-1316-42a7-8c30-3a752ed21c09</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.8" />
</ItemGroup>
</Project>