ef核心迁移不能使用Secret Manager [英] ef core migration can't use secret manager
问题描述
当我创建.net核心Web应用程序时,我在测试过程中使用了秘密管理器.我通常可以创建一个新的Web项目(MVC和Web API),右键单击该项目,然后选择管理用户机密".这将打开一个json文件,在其中添加机密信息.然后,我在startup.cs中使用以下代码:
When I create .net core web applications, I use the secret manager during testing. I am generally able to create a new web project (mvc and web api), right click on the project and select "manage user secrets". This opens a json file where I add the secrets. I then use this in my startup.cs something like this:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(Configuration["connectionString"]));
该网站可以正常运行,并且可以很好地连接到数据库.但是,当我尝试使用ef核心迁移命令(例如add-migration
)时,它们似乎无法从密码管理器访问连接字符串.我收到错误消息:连接字符串不能为空".当我用实际的字符串硬编码Configuration["connectionString"]
时,错误消失了.我已经在线检查并检查了.csproj文件,它们已经包含以下行:
The website works fine with this and connects well to the database. However when I try using ef core migration commands such as add-migration
, they don't seem to be able to access the connection string from the secret manager. I get the error saying "connection string can't be null". The error is gone when I hard code Configuration["connectionString"]
with the actual string. I have checked online and checked the .csproj file, they already contain the following lines:
<UserSecretsId>My app name</UserSecretsId>
后来:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
我需要添加什么以便迁移可以访问连接字符串吗?
Is there anything I need to add so the migrations can access the connection string?
更新
我在上下文类中只有一个构造函数:
I only have one constructor in the context class:
public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options)
{
}
推荐答案
我目前也遇到了这个确切的问题.我现在想出了一种行之有效的解决方案,但人们可能认为充其量只是一团糟.
I am currently coming across this exact problem as well. I have come up with a solution that works for now, but one may consider messy at best.
我已经创建了一个配置类,该类可以在请求时提供配置接口:
I have created a Configuration Class that provides the Configuration Interface when requested:
public static class Configuration
{
public static IConfiguration GetConfiguration()
{
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
.AddUserSecrets<Startup>()
.AddEnvironmentVariables()
.Build();
}
}
然后,在迁移中,您可以获取配置文件并按如下方式访问其UserSecrets:
In the Migration, you can then get the Configuration File and access its UserSecrets like this:
protected override void Up(MigrationBuilder migrationBuilder)
{
var conf = Configuration.GetConfiguration();
var secret = conf["Secret"];
}
我已经测试了使用这些用户密码创建SQL脚本的方法,并且它可以正常工作(显然,您不希望保留该脚本,因为它会暴露实际的密码).
I have tested creating a SQL Script with these User Secrets, and it works (you obviously wouldn't want to keep the Script laying around since it would expose the actual secret).
更新
上面的配置也可以在BuildWebHost
方法中设置为Program.cs类:
The above config can also be set up into Program.cs class in the BuildWebHost
method:
var config = new ConfigurationBuilder().AddUserSecrets<Startup>().Build();
return WebHost.CreateDefaultBuilder(args).UseConfiguration(config)...Build()
或者在启动构造函数中,如果使用公约
Or in the Startup Constructor if using that Convention
更新2(说明)
事实证明,此问题是因为迁移脚本在环境设置为生产"的情况下运行.秘密管理器已预设为仅在开发"环境中工作(有充分的理由). .AddUserSecrets<Startup>()
函数只是为所有环境添加秘密.
It turns out this issue is because the migration scripts runs with the environment set to "Production". The secret manager is pre-set to only work in "Development" environment (for a good reason). The .AddUserSecrets<Startup>()
function simply adds the secrets for all environment.
为确保未将其设置为生产服务器,我注意到了两种解决方案,建议在此处使用一种解决方案:
To ensure that this isn't set to your production server, there are two solutions I have noticed, one is suggested here: https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell
在运行之前设置env:ASPNETCORE_ENVIRONMENT以指定ASP.NET Core环境.
Set env:ASPNETCORE_ENVIRONMENT before running to specify the ASP.NET Core environment.
此解决方案意味着以后无需在计算机上创建的每个项目中都设置.AddUserSecrets<Startup>()
.但是,如果您恰巧要在其他计算机上共享该项目,则需要在每台计算机上进行配置.
This solution would mean there is no need to set .AddUserSecrets<Startup>()
on every project created on the computer in future. However if you happen to be sharing this project across other computers, this needs to be configured on each computer.
第二种解决方案是仅在调试版本中设置.AddUserSecrets<Startup>()
,如下所示:
The second solution is to set the .AddUserSecrets<Startup>()
only on debug build like this:
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true)
#if DEBUG
.AddUserSecrets<Startup>()
#endif
.AddEnvironmentVariables()
.Build();
其他信息
可以将配置接口传递给其构造函数中的控制器,即
The Configuration Interface can be passed to Controllers in their Constructor, i.e.
private readonly IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
_configuration = configuration;
}
因此,通过访问_configuration["secret"]
,可以在该控制器中访问任何机密和应用程序设置.
Thus, any Secrets and Application Setting are accessible in that Controller by accessing _configuration["secret"]
.
但是,如果要从Web应用程序本身外部的迁移文件"访问应用程序机密,则需要遵循原始答案,因为没有简便的方法(据我所知)否则将访问这些机密(我可以想到的一个用例是,使用管理员和主密码为数据库播种).
However, if you want to access Application Secrets from, for example, a Migration-File, which exists outside of the Web Application itself, you need to adhere to the original answer because there's no easy way (that I know of) to access those secrets otherwise (one use case I can think of would be seeding the Database with an Admin and a Master Password).
这篇关于ef核心迁移不能使用Secret Manager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!