ef核心迁移不能使用Secret Manager [英] ef core migration can't use secret manager

本文介绍了ef核心迁移不能使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆