本文主要记录 ASP.NET Core / 通用 Host 下配置加载与密钥存放:环境变量如何切换 appsettings.{Environment}.json、本地 User Secrets 防泄露、以及 dotnet ef 跟随同一套环境变量读连接串。

由 queue 碎片 environment-variables、run-with-config、api-key-user-secrets、ef-generate 合并改写。接 Hello World / MediaInfoEF Core + SQLite真实 API Key、连接串勿提交 Git。

配置加载机制

默认(Minimal Hosting)大致顺序:

appsettings.json
appsettings.{Environment}.json   ← 后加载覆盖前者
环境变量、命令行等(优先级更高,视 Host 默认)

{Environment} 由下列变量决定:

变量常见场景
ASPNETCORE_ENVIRONMENTWeb / ASP.NET Core
DOTNET_ENVIRONMENTGeneric Host

二者都设时,Web 场景通常以 ASPNETCORE_ENVIRONMENT 为准(以当前 SDK 模板行为为准)。未设置时,dotnet run 本地 Web 模板默认多为 Development,因而会加载 appsettings.Development.json

用环境切换配置文件

PowerShell(当前会话):

$env:ASPNETCORE_ENVIRONMENT = "Production"
dotnet run

CMD:

set ASPNETCORE_ENVIRONMENT=Production
dotnet run

Linux / macOS / WSL:

ASPNETCORE_ENVIRONMENT=Production dotnet run

验证当前环境:在启动日志中查看 Hosting environment,或临时打印 builder.Environment.EnvironmentName

说明:决定加载哪份 JSON 的是 Hosting Environment,不是 Debug/Release 编译配置。

环境变量速查

ASPNETCORE_ENVIRONMENT / DOTNET_ENVIRONMENT 为例。

Windows PowerShell

# 查看
$env:ASPNETCORE_ENVIRONMENT
Get-ChildItem Env: | Where-Object Name -Like "*ASPNET*"

# 临时(当前窗口)
$env:ASPNETCORE_ENVIRONMENT = "Production"

# 永久(用户级,新开终端生效)
[System.Environment]::SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Production", "User")

# 删除会话内
Remove-Item Env:ASPNETCORE_ENVIRONMENT -ErrorAction SilentlyContinue

Windows CMD

echo %ASPNETCORE_ENVIRONMENT%
set ASPNETCORE_ENVIRONMENT=Production
setx ASPNETCORE_ENVIRONMENT Production

setx 只影响打开的终端。

Linux / macOS

echo $ASPNETCORE_ENVIRONMENT
export ASPNETCORE_ENVIRONMENT=Production
# 持久化可写入 ~/.bashrc 或 systemd unit Environment=

嵌套配置键映射到环境变量时,常用 __ 双下划线,例如 TmdbSettings:ApiKeyTmdbSettings__ApiKey

User Secrets(本地密钥)

为什么需要

appsettings.json / appsettings.Development.json 若被 Git 跟踪,明文 API Key 极易被扫描盗用。本地开发推荐 User Secrets:密钥写在用户配置目录,不在仓库内。

初始化与写入

在项目根目录:

dotnet user-secrets init
dotnet user-secrets set "TmdbSettings:ApiKey" "<your-api-key>"

init 会在 .csproj 写入 UserSecretsId。密钥物理路径示意:

OS路径
Windows%APPDATA%\Microsoft\UserSecrets\<UserSecretsId>\secrets.json
Linux/macOS~/.microsoft/usersecrets/<UserSecretsId>/secrets.json

仓库内配置可只留占位:

"TmdbSettings": {
  "ApiKey": "",
  "DefaultLanguage": "zh-CN"
}

读取代码仍用 IConfiguration 键名(如 TmdbSettings:ApiKey),无需为 User Secrets 单独改业务代码。

是否区分 Development / Production?

  • 存储层:user-secrets 按环境分文件,只按 UserSecretsId 绑定项目。
  • 加载层:默认 Web 模板往往只在 IsDevelopment()AddUserSecrets,因此 Production 默认不会读本地 secrets。
  • 部署到 Docker/服务器时,用环境变量或密钥管理系统注入同名键(如 TmdbSettings__ApiKey)。

查看已设置项:

dotnet user-secrets list

元数据路径配置(示例)

除密钥外,本地数据目录也可放在配置中(非密钥、可进 Development 配置或本机覆盖):

"MediaConfig": {
  "MetadataPath": "Z:\\octans_metadata",
  "LibraryPaths": {
    "Movies": "Z:\\testmovies",
    "TvShows": "Z:\\testtvshows"
  }
}

Linux 部署可改为 /app/data/octans_metadata 等;大文件目录应挂卷,勿打进镜像层。

EF Core 迁移与环境

dotnet ef database update / migrations add 会启动项目构建 Host 并读 IConfiguration,规则与 dotnet run 相同:依赖当前 ASPNETCORE_ENVIRONMENT(等)选择 appsettings.*.json 与连接串。

# 使用 Production 连接串做迁移(慎用:确认目标库)
$env:ASPNETCORE_ENVIRONMENT = "Production"
dotnet ef database update
ASPNETCORE_ENVIRONMENT=Development dotnet ef database update

注意:

  • 连错库会直接改结构,生产前再三确认连接串与环境名。
  • 仅 Development 时 User Secrets 中的连接串才可能生效;Production 迁移应依赖显式环境变量或 CI 密钥,而不是本机 secrets。
  • -- --environment 类传参是否被 Host 解析取决于模板;最稳妥是设环境变量(待确认你项目是否自定义了命令行解析)。

验证清单

做法
环境生效ASPNETCORE_ENVIRONMENT 后看加载的 json / 日志中的 environment
Secretsdotnet user-secrets list 有键;仓库内无真实 Key
配置优先级同键时环境变量覆盖 appsettings(默认 Host)
EF指定环境后 database update 连到预期库(可用只读探测或临时库验证)

注意事项

  • 不要把 secrets.json 或含密码的 appsettings.Production.json 提交进 Git。
  • CI/CD 用 runner 密钥或 vault,不复用个人 User Secrets。
  • 永久环境变量影响面大,优先会话级 export/$env: 做切换。
  • 轮换已泄露过的 API Key。

参考资料