chr*_*oli 1 .net c# visual-studio azure-functions .net-6.0
我环顾四周,很惊讶没有人问过这个问题,但我正在尝试将用户机密与我的 Azure Function 应用程序(.NET 6,v4)一起使用。该值永远不会填充“我从 Visual Studio 本地运行”。
Function1.cs
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
var secret = Environment.GetEnvironmentVariable("mysecret");
return new OkObjectResult($"Secret is: {secret}");
}
}
Run Code Online (Sandbox Code Playgroud)
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
Run Code Online (Sandbox Code Playgroud)
secrets.json
{
"mysecret": "test1",
"Values:mysecret": "test2"
}
Run Code Online (Sandbox Code Playgroud)
FunctionApp1.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<UserSecretsId>24c7ab90-4094-49a9-94ef-c511ac530526</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
端点返回:“秘密是:”,我希望它返回“秘密是:test1”或“秘密是:test2”
但是,当我将其更改local.settings.json为它时,它会起作用:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"mysecret": "test3"
}
}
Run Code Online (Sandbox Code Playgroud)
如何将用户机密正确传递到 local.settings.json?我猜它们不会显示为环境变量。
总而言之:
可能不是最好的办法,但可以这样解决。当有我想要签入的设置时,我也这样做过几次。但是,如果您确实有可以签入的设置,您可能会重新考虑将它们添加到自己的类中,除非它们应该在部署期间被覆盖。
在我看来,您应该保留local.settings.json而不是尝试将其替换为appsettings.json,因为通常需要一些值才能使其运行如下:
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
},
Run Code Online (Sandbox Code Playgroud)
安装 NuGetMicrosoft.Extensions.Configuration.UserSecrets
设置。local.settings.json Copy to Output DirectoryCopy if newer
对于 .NET 5 < ,修改Program.cs为如下所示。已测试至 .NET 7:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration((hostContext, config) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
config.AddJsonFile("local.settings.json");
config.AddUserSecrets<Program>();
}
})
.ConfigureServices((hostContext, services) =>
{
var connectionString = hostContext.Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
var configuration = hostContext.Configuration;
var settings = new Settings();
configuration.Bind(settings);
services.AddSingleton(settings);
}
)
.Build();
host.Run();
public class Settings
{
public ConnectionStrings ConnectionStrings { get; set; } = new ConnectionStrings();
}
public class ConnectionStrings
{
public string DefaultConnection { get; set; } = "";
}
Run Code Online (Sandbox Code Playgroud)
唯一真正需要的是下面的内容,但我喜欢展示现实世界中更完整的示例:
.ConfigureAppConfiguration((hostContext, config) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
config.AddJsonFile("local.settings.json");
config.AddUserSecrets<Program>();
}
})
Run Code Online (Sandbox Code Playgroud)
您现在可以注入Settings构造函数中的任何内容,如果存在秘密,它们将被覆盖。
public class TimerTrigger
{
private readonly ILogger _logger;
private readonly ApplicationDbContext _dbContext;
private readonly Settings _settings;
public TimerTrigger(ILoggerFactory loggerFactory, ApplicationDbContext dbContext, Settings settings)
{
_logger = loggerFactory.CreateLogger<TimerTrigger>();
_dbContext = dbContext;
_settings=settings;
}
[Function("TimerTrigger")]
public void Run([TimerTrigger("0 */1 * * * *")] MyInfo myTimer)
{
if (myTimer is not null && myTimer.ScheduleStatus is not null)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
_logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
var defaultConnection = _settings.ConnectionStrings.DefaultConnection;
Run Code Online (Sandbox Code Playgroud)
长答案:
使用 Visual Studio 创建的 ASP.NET Core Web 应用程序dotnet new会为 .NET 7 生成与此类似的代码:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Run Code Online (Sandbox Code Playgroud)
WebApplication.CreateBuilder使用预配置的默认值初始化WebApplicationBuilder类的新实例。初始化WebApplicationBuilder (builder)提供默认配置,并在 EnvironmentName 为Development时调用AddUserSecrets:
该方法AddUserSecrets位于Microsoft.Extensions.Configuration包的命名空间中Microsoft.Extensions.Configuration.UserSecrets
https://www.nuget.org/packages/Microsoft.Extensions.Configuration.UserSecrets/
如果我们看看它是如何Environment variables工作的:
环境变量用于避免将应用程序机密存储在代码或本地配置文件中。环境变量会覆盖所有先前指定的配置源的配置值。
鉴于这local.settings.json意味着是本地的,并且.gitignore添加 Azure Functions 项目时创建的默认值会显式忽略它,因此就像秘密一样工作:
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# Azure Functions localsettings file
local.settings.json
Run Code Online (Sandbox Code Playgroud)
应用程序机密不会签入源代码管理。
但是,如果您仍然想使用机密管理器工具和机密存储,请阅读我的 TLDR。
示例值:
本地.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"Movies:ServiceApiKey": "--SECRET--"
},
"ConnectionStrings": {
"DefaultConnection": "--SECRET--"
}
}
Run Code Online (Sandbox Code Playgroud)
秘密.json:
{
"Movies": {
"ServiceApiKey": "12345"
}
}
Run Code Online (Sandbox Code Playgroud)
读数值:
var moviesApiKeyConfig = _config["Movies:ServiceApiKey"];
var moviesApiKeySettings = _settings.Movies.ServiceApiKey;
var moviesApiKeyEnvironmentVariable = Environment.GetEnvironmentVariable("Movies:ServiceApiKey");
Run Code Online (Sandbox Code Playgroud)
正如您所看到的IConfiguration,Microsoft.Extensions.Configuration按预期拾取秘密,但Environment.GetEnvironmentVariable没有。也符合文档的预期。