Jakeuj's Notes master Help

ASP.NET Core User Secrets 只在 Development 載入

ASP.NET Core Web App 使用 WebApplication.CreateBuilder(args) 時,預設組態會在 EnvironmentNameDevelopment 時呼叫 AddUserSecrets

所以一般 Web 專案的重點不是把秘密寫進 appsettings.json ,而是先建立 UserSecretsId ,再用 dotnet user-secrets 管理本機開發秘密。

重點判斷

  • User Secrets 適合本機開發,不適合測試、Staging 或 Production。

  • 使用 Microsoft.NET.Sdk.Web 的 ASP.NET Core Web 專案,通常不需要在 Program.cs 手動補 AddUserSecrets

  • 如果是 Console App、Worker Service、自訂 ConfigurationBuilder ,或你覆寫了預設設定載入流程,才需要自己判斷環境後呼叫 AddUserSecrets

  • User Secrets 不會加密,只是把本機開發用秘密放在使用者設定檔底下,避免簽入 Git。

建立 User Secrets

先在專案目錄初始化 UserSecretsId

dotnet user-secrets init

這會在 .csproj 加入類似下列設定:

<PropertyGroup> <UserSecretsId>aspnet-core-user-secrets-demo</UserSecretsId> </PropertyGroup>

再把本機開發用的秘密寫進 Secret Manager:

dotnet user-secrets set "Movies:ServiceApiKey" "<api-key>" dotnet user-secrets set "ConnectionStrings:Default" "<local-development-connection-string>"

確認目前專案底下有哪些秘密:

dotnet user-secrets list

secrets.json 不一定要扁平化

實測直接修改 secrets.json 時,不一定要把 JSON 結構扁平化成 Movies:ServiceApiKey 這種 key,也可以使用一般巢狀 JSON。

例如這樣可以正常透過 Movies:ConnectionStringMovies:ServiceApiKey 讀取:

{ "Movies": { "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true", "ServiceApiKey": "12345" } }

也可以自行扁平化,看自己維護起來哪種比較順手:

{ "Movies:ServiceApiKey": "12345" }

不過透過 dotnet user-secrets setdotnet user-secrets remove 修改後,工具可能會把結構轉成扁平化形式。這部分可參考官方文件的 在 Visual Studio 中 JSON 結構扁平化

一般 Web 專案不必手動加

Minimal API 或 ASP.NET Core Web 專案常見的啟動程式如下:

var builder = WebApplication.CreateBuilder(args); var apiKey = builder.Configuration["Movies:ServiceApiKey"]; var app = builder.Build(); app.MapGet("/", () => apiKey); app.Run();

只要目前環境是 DevelopmentWebApplication.CreateBuilder(args) 預設會把 User Secrets 加進組態來源。也就是說,開發機讀得到 dotnet user-secrets set 寫入的值,但部署到非 Development 環境時不會自動讀取同一份 User Secrets。

何時需要手動呼叫 AddUserSecrets

預設 Web 專案不必重複註冊。只有在你自己建立 ConfigurationBuilder ,或在 Console App、Worker Service 等非預設 Web 組態流程中使用 User Secrets 時,才需要把判斷寫清楚:

using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; var environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? Environments.Production; var configurationBuilder = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables(); if (environmentName == Environments.Development) { configurationBuilder.AddUserSecrets<Program>(); } var configuration = configurationBuilder.Build();

這段的重點是:只有 EnvironmentName 等於 Development 時才呼叫 AddUserSecrets ,避免其他環境意外依賴開發機上的秘密。

Microsoft.NET.Sdk.Web 專案如果找不到 AddUserSecrets ,先安裝 User Secrets 組態套件:

dotnet add package Microsoft.Extensions.Configuration.UserSecrets

讀取設定值

User Secrets 進入組態系統後,讀法和 appsettings.json 、環境變數相同:

var apiKey = builder.Configuration["Movies:ServiceApiKey"]; var connectionString = builder.Configuration.GetConnectionString("Default");

如果要綁定成 options 類別,也可以照一般 Options pattern 寫法處理:

builder.Services.Configure<MovieOptions>( builder.Configuration.GetSection("Movies"));

補充說明

  • Production 建議改用環境變數、部署平台的 secret 管理功能,或 Azure Key Vault 這類受控秘密保存庫。

  • dotnet user-secrets 的值跟專案的 UserSecretsId 綁定;不同專案如果需要共用同一組開發秘密,可以使用相同的 UserSecretsId ,但要刻意管理,避免混淆。

Rider

rider_user_secrets.png

參考資料

20 April 2026