在 ASP.NET Core 中的開發中安全儲存應用程式秘密Safe storage of app secrets in development in ASP.NET Core

Rick AndersonKirk LarkinDaniel RothScott AddieBy Rick Anderson, Kirk Larkin, Daniel Roth, and Scott Addie

查看或下載範例程式碼如何下載View or download sample code (how to download)

本檔說明在開發電腦上開發 ASP.NET Core 應用程式期間,儲存和取得敏感性資料的技術。This document explains techniques for storing and retrieving sensitive data during development of an ASP.NET Core app on a development machine. 絕對不要將密碼或其他敏感性資料儲存在原始程式碼中。Never store passwords or other sensitive data in source code. 生產秘密不應用於開發或測試。Production secrets shouldn't be used for development or test. 秘密不應該與應用程式一起部署。Secrets shouldn't be deployed with the app. 相反地,您應該透過受控制的方式(例如環境變數、Azure Key Vault 等),在生產環境中提供秘密。您可以使用Azure Key Vault 設定提供者來儲存及保護 Azure 測試和生產密碼。Instead, secrets should be made available in the production environment through a controlled means like environment variables, Azure Key Vault, etc. You can store and protect Azure test and production secrets with the Azure Key Vault configuration provider.

環境變數Environment variables

環境變數是用來避免在程式碼或本機設定檔案中儲存應用程式秘密。Environment variables are used to avoid storage of app secrets in code or in local configuration files. 環境變數會覆寫所有先前指定之設定來源的設定值。Environment variables override configuration values for all previously specified configuration sources.

請考慮啟用個別使用者帳戶安全性的 ASP.NET Core web 應用程式。Consider an ASP.NET Core web app in which Individual User Accounts security is enabled. 預設的資料庫連接字串會包含在具有索引鍵之檔案的專案appsettings.jsDefaultConnectionA default database connection string is included in the project's appsettings.json file with the key DefaultConnection. 預設連接字串適用于 LocalDB,它會在使用者模式中執行,而且不需要密碼。The default connection string is for LocalDB, which runs in user mode and doesn't require a password. 在應用程式部署期間, DefaultConnection 可以使用環境變數的值來覆寫金鑰值。During app deployment, the DefaultConnection key value can be overridden with an environment variable's value. 環境變數可能會儲存具有敏感性認證的完整連接字串。The environment variable may store the complete connection string with sensitive credentials.

警告

環境變數通常會儲存為純文字、未加密的文字。Environment variables are generally stored in plain, unencrypted text. 如果電腦或進程遭到入侵,則不受信任的合作物件可以存取環境變數。If the machine or process is compromised, environment variables can be accessed by untrusted parties. 可能需要其他措施來防止洩漏使用者秘密。Additional measures to prevent disclosure of user secrets may be required.

:分隔符不適用於所有平臺上的環境變數分層鍵。The : separator doesn't work with environment variable hierarchical keys on all platforms. __,雙下劃線是:__, the double underscore, is:

  • 支援所有平臺。Supported by all platforms. 例如:,Bash不支援分隔符__,但是 。For example, the : separator is not supported by Bash, but __ is.
  • 自動取代為:Automatically replaced by a :

秘密管理員Secret Manager

秘密管理員工具會在 ASP.NET Core 專案的開發期間儲存機密資料。The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. 在此內容中,有一段敏感性資料是應用程式密碼。In this context, a piece of sensitive data is an app secret. 應用程式密碼會儲存在專案樹狀結構的不同位置。App secrets are stored in a separate location from the project tree. 應用程式密碼會與特定專案建立關聯,或在數個專案之間共用。The app secrets are associated with a specific project or shared across several projects. 應用程式秘密不會簽入原始檔控制中。The app secrets aren't checked into source control.

警告

秘密管理員工具不會加密儲存的秘密,也不應視為受信任的存放區。The Secret Manager tool doesn't encrypt the stored secrets and shouldn't be treated as a trusted store. 僅供開發之用。It's for development purposes only. 金鑰和值會儲存在使用者設定檔目錄的 JSON 設定檔中。The keys and values are stored in a JSON configuration file in the user profile directory.

密碼管理員工具的運作方式How the Secret Manager tool works

秘密管理員工具會將執行詳細資料(例如儲存值的位置和方式)抽象化出來。The Secret Manager tool abstracts away the implementation details, such as where and how the values are stored. 您可以使用此工具,而不需要知道這些執行方式的詳細資料。You can use the tool without knowing these implementation details. 這些值會儲存在本機電腦上系統保護的使用者設定檔資料夾中的 JSON 設定檔案:The values are stored in a JSON configuration file in a system-protected user profile folder on the local machine:

檔案系統路徑:File system path:

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

在先前的檔案路徑中, <user_secrets_id> 將取代為 UserSecretsId .csproj檔案中指定的值。In the preceding file paths, replace <user_secrets_id> with the UserSecretsId value specified in the .csproj file.

請勿撰寫依賴秘密管理員工具所儲存之資料位置或格式的程式碼。Don't write code that depends on the location or format of data saved with the Secret Manager tool. 這些執行詳細資料可能會變更。These implementation details may change. 例如,秘密值不會加密,但未來可能會是。For example, the secret values aren't encrypted, but could be in the future.

啟用秘密儲存Enable secret storage

「秘密管理員」工具會針對儲存在使用者設定檔中的專案特定設定進行操作。The Secret Manager tool operates on project-specific configuration settings stored in your user profile.

「密碼管理員」工具 init 在 .NET Core SDK 3.0.100 或更新版本中包含一個命令。The Secret Manager tool includes an init command in .NET Core SDK 3.0.100 or later. 若要使用使用者秘密,請在專案目錄中執行下列命令:To use user secrets, run the following command in the project directory:

dotnet user-secrets init

上述命令會 UserSecretsIdPropertyGroup .csproj檔案的中新增專案。The preceding command adds a UserSecretsId element within a PropertyGroup of the .csproj file. 根據預設,的內部文字 UserSecretsId 是 GUID。By default, the inner text of UserSecretsId is a GUID. 內部文字是任意的,但對專案而言是唯一的。The inner text is arbitrary, but is unique to the project.

<PropertyGroup>
  <TargetFramework>netcoreapp3.1</TargetFramework>
  <UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>

在 Visual Studio 中,以滑鼠右鍵按一下方案總管中的專案,然後從內容功能表中選取 [管理使用者秘密]。In Visual Studio, right-click the project in Solution Explorer, and select Manage User Secrets from the context menu. 此手勢會將已 UserSecretsId 填入 GUID 的元素新增至 .csproj檔案。This gesture adds a UserSecretsId element, populated with a GUID, to the .csproj file.

設定密碼Set a secret

定義由金鑰和其值組成的應用程式密碼。Define an app secret consisting of a key and its value. 此密碼與專案的值相關聯 UserSecretsIdThe secret is associated with the project's UserSecretsId value. 例如,從 .csproj檔案所在的目錄執行下列命令:For example, run the following command from the directory in which the .csproj file exists:

dotnet user-secrets set "Movies:ServiceApiKey" "12345"

在上述範例中,冒號表示 Movies 是具有屬性的物件常值 ServiceApiKeyIn the preceding example, the colon denotes that Movies is an object literal with a ServiceApiKey property.

秘密管理員工具也可以從其他目錄中使用。The Secret Manager tool can be used from other directories too. 使用 --project 選項來提供 .csproj檔案所在的檔案系統路徑。Use the --project option to supply the file system path at which the .csproj file exists. 例如:For example:

dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"

Visual Studio 中的 JSON 結構簡維JSON structure flattening in Visual Studio

Visual Studio 的 [管理使用者秘密] 手勢會在文字編輯器中開啟檔案secrets.jsVisual Studio's Manage User Secrets gesture opens a secrets.json file in the text editor. secrets.js的內容取代為要儲存的機碼值組。Replace the contents of secrets.json with the key-value pairs to be stored. 例如:For example:

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

JSON 結構會在透過或進行修改之後壓平合併 dotnet user-secrets remove dotnet user-secrets setThe JSON structure is flattened after modifications via dotnet user-secrets remove or dotnet user-secrets set. 例如,執行會折迭 dotnet user-secrets remove "Movies:ConnectionString" Movies 物件常值。For example, running dotnet user-secrets remove "Movies:ConnectionString" collapses the Movies object literal. 修改過的檔案如下所示:The modified file resembles the following:

{
  "Movies:ServiceApiKey": "12345"
}

設定多個秘密Set multiple secrets

您可以透過將 JSON 傳送至命令的方式來設定密碼批次 setA batch of secrets can be set by piping JSON to the set command. 在下列範例中,檔案內容上的input.js會以管道傳送至 set 命令。In the following example, the input.json file's contents are piped to the set command.

開啟命令 shell,然後執行下列命令:Open a command shell, and execute the following command:

type .\input.json | dotnet user-secrets set

存取秘密Access a secret

ASP.NET Core 設定 API提供秘密管理員密碼的存取權。The ASP.NET Core Configuration API provides access to Secret Manager secrets.

當專案呼叫 CreateDefaultBuilder 以預先設定的預設值來初始化主機的新實例時,會自動在開發模式中新增使用者秘密設定來源。The user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults. CreateDefaultBuilderAddUserSecrets當為時 EnvironmentName 呼叫 DevelopmentCreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

CreateDefaultBuilder 未呼叫,請呼叫以明確新增使用者秘密設定來源 AddUserSecretsWhen CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets. AddUserSecrets只有當應用程式在開發環境中執行時才會呼叫,如下列範例所示:Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example:

var host = new HostBuilder()
    .ConfigureAppConfiguration((hostContext, builder) =>
    {
        // Add other providers for JSON, etc.

        if (hostContext.HostingEnvironment.IsDevelopment())
        {
            builder.AddUserSecrets<Program>();
        }
    })
    .Build();

您可以透過 API 來抓取使用者秘密 ConfigurationUser secrets can be retrieved via the Configuration API:

public class Startup
{
    private string _moviesApiKey = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        _moviesApiKey = Configuration["Movies:ServiceApiKey"];
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
            await context.Response.WriteAsync($"Secret is {result}");
        });
    }
}

將秘密對應至 POCOMap secrets to a POCO

將整個物件常值對應至 POCO (具有屬性的簡單 .NET 類別),對於匯總相關屬性很有用。Mapping an entire object literal to a POCO (a simple .NET class with properties) is useful for aggregating related properties.

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

若要將上述密碼對應到 POCO,請使用 Configuration API 的物件圖形系結功能。To map the preceding secrets to a POCO, use the Configuration API's object graph binding feature. 下列程式碼會系結至自訂 MovieSettings POCO 並存取 ServiceApiKey 屬性值:The following code binds to a custom MovieSettings POCO and accesses the ServiceApiKey property value:

var moviesConfig = Configuration.GetSection("Movies")
                                .Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;

Movies:ConnectionStringMovies:ServiceApiKey 密碼會對應至中的個別屬性 MovieSettingsThe Movies:ConnectionString and Movies:ServiceApiKey secrets are mapped to the respective properties in MovieSettings:

public class MovieSettings
{
    public string ConnectionString { get; set; }

    public string ServiceApiKey { get; set; }
}

使用秘密取代字串String replacement with secrets

以純文字儲存密碼並不安全。Storing passwords in plain text is insecure. 例如,儲存在appsettings.js中的資料庫連接字串可能會包含指定使用者的密碼:For example, a database connection string stored in appsettings.json may include a password for the specified user:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
  }
}

更安全的方法是將密碼儲存為秘密。A more secure approach is to store the password as a secret. 例如:For example:

dotnet user-secrets set "DbPassword" "pass123"

Passwordappsettings.json的連接字串中移除索引鍵/值組。Remove the Password key-value pair from the connection string in appsettings.json. 例如:For example:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
  }
}

您可以在物件的屬性上設定密碼的值 SqlConnectionStringBuilder Password ,以完成連接字串:The secret's value can be set on a SqlConnectionStringBuilder object's Password property to complete the connection string:

public class Startup
{
    private string _connection = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var builder = new SqlConnectionStringBuilder(
            Configuration.GetConnectionString("Movies"));
        builder.Password = Configuration["DbPassword"];
        _connection = builder.ConnectionString;
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync($"DB Connection: {_connection}");
        });
    }
}

列出秘密List the secrets

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets list

即會出現下列輸出:The following output appears:

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

在上述範例中,索引鍵名稱中的冒號代表secrets.js中的物件階層。In the preceding example, a colon in the key names denotes the object hierarchy within secrets.json.

移除單一秘密Remove a single secret

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets remove "Movies:ConnectionString"

應用程式在檔案上的secrets.js已修改為移除與機碼相關聯的機碼值組 MoviesConnectionStringThe app's secrets.json file was modified to remove the key-value pair associated with the MoviesConnectionString key:

{
  "Movies": {
    "ServiceApiKey": "12345"
  }
}

dotnet user-secrets list會顯示下列訊息:dotnet user-secrets list displays the following message:

Movies:ServiceApiKey = 12345

移除所有秘密Remove all secrets

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets clear

應用程式的所有使用者秘密已從檔案中的secrets.js刪除:All user secrets for the app have been deleted from the secrets.json file:

{}

dotnet user-secrets list執行會顯示下列訊息:Running dotnet user-secrets list displays the following message:

No secrets configured for this application.

其他資源Additional resources

Rick AndersonDaniel RothScott AddieBy Rick Anderson, Daniel Roth, and Scott Addie

查看或下載範例程式碼如何下載View or download sample code (how to download)

本檔說明在開發電腦上開發 ASP.NET Core 應用程式期間,儲存和取得敏感性資料的技術。This document explains techniques for storing and retrieving sensitive data during development of an ASP.NET Core app on a development machine. 絕對不要將密碼或其他敏感性資料儲存在原始程式碼中。Never store passwords or other sensitive data in source code. 生產秘密不應用於開發或測試。Production secrets shouldn't be used for development or test. 秘密不應該與應用程式一起部署。Secrets shouldn't be deployed with the app. 相反地,您應該透過受控制的方式(例如環境變數、Azure Key Vault 等),在生產環境中提供秘密。您可以使用Azure Key Vault 設定提供者來儲存及保護 Azure 測試和生產密碼。Instead, secrets should be made available in the production environment through a controlled means like environment variables, Azure Key Vault, etc. You can store and protect Azure test and production secrets with the Azure Key Vault configuration provider.

環境變數Environment variables

環境變數是用來避免在程式碼或本機設定檔案中儲存應用程式秘密。Environment variables are used to avoid storage of app secrets in code or in local configuration files. 環境變數會覆寫所有先前指定之設定來源的設定值。Environment variables override configuration values for all previously specified configuration sources.

請考慮啟用個別使用者帳戶安全性的 ASP.NET Core web 應用程式。Consider an ASP.NET Core web app in which Individual User Accounts security is enabled. 預設的資料庫連接字串會包含在具有索引鍵之檔案的專案appsettings.jsDefaultConnectionA default database connection string is included in the project's appsettings.json file with the key DefaultConnection. 預設連接字串適用于 LocalDB,它會在使用者模式中執行,而且不需要密碼。The default connection string is for LocalDB, which runs in user mode and doesn't require a password. 在應用程式部署期間, DefaultConnection 可以使用環境變數的值來覆寫金鑰值。During app deployment, the DefaultConnection key value can be overridden with an environment variable's value. 環境變數可能會儲存具有敏感性認證的完整連接字串。The environment variable may store the complete connection string with sensitive credentials.

警告

環境變數通常會儲存為純文字、未加密的文字。Environment variables are generally stored in plain, unencrypted text. 如果電腦或進程遭到入侵,則不受信任的合作物件可以存取環境變數。If the machine or process is compromised, environment variables can be accessed by untrusted parties. 可能需要其他措施來防止洩漏使用者秘密。Additional measures to prevent disclosure of user secrets may be required.

:分隔符不適用於所有平臺上的環境變數分層鍵。The : separator doesn't work with environment variable hierarchical keys on all platforms. __,雙下劃線是:__, the double underscore, is:

  • 支援所有平臺。Supported by all platforms. 例如:,Bash不支援分隔符__,但是 。For example, the : separator is not supported by Bash, but __ is.
  • 自動取代為:Automatically replaced by a :

秘密管理員Secret Manager

秘密管理員工具會在 ASP.NET Core 專案的開發期間儲存機密資料。The Secret Manager tool stores sensitive data during the development of an ASP.NET Core project. 在此內容中,有一段敏感性資料是應用程式密碼。In this context, a piece of sensitive data is an app secret. 應用程式密碼會儲存在專案樹狀結構的不同位置。App secrets are stored in a separate location from the project tree. 應用程式密碼會與特定專案建立關聯,或在數個專案之間共用。The app secrets are associated with a specific project or shared across several projects. 應用程式秘密不會簽入原始檔控制中。The app secrets aren't checked into source control.

警告

秘密管理員工具不會加密儲存的秘密,也不應視為受信任的存放區。The Secret Manager tool doesn't encrypt the stored secrets and shouldn't be treated as a trusted store. 僅供開發之用。It's for development purposes only. 金鑰和值會儲存在使用者設定檔目錄的 JSON 設定檔中。The keys and values are stored in a JSON configuration file in the user profile directory.

密碼管理員工具的運作方式How the Secret Manager tool works

秘密管理員工具會將執行詳細資料(例如儲存值的位置和方式)抽象化出來。The Secret Manager tool abstracts away the implementation details, such as where and how the values are stored. 您可以使用此工具,而不需要知道這些執行方式的詳細資料。You can use the tool without knowing these implementation details. 這些值會儲存在本機電腦上系統保護的使用者設定檔資料夾中的 JSON 設定檔案:The values are stored in a JSON configuration file in a system-protected user profile folder on the local machine:

檔案系統路徑:File system path:

%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json

在先前的檔案路徑中, <user_secrets_id> 將取代為 UserSecretsId .csproj檔案中指定的值。In the preceding file paths, replace <user_secrets_id> with the UserSecretsId value specified in the .csproj file.

請勿撰寫依賴秘密管理員工具所儲存之資料位置或格式的程式碼。Don't write code that depends on the location or format of data saved with the Secret Manager tool. 這些執行詳細資料可能會變更。These implementation details may change. 例如,秘密值不會加密,但未來可能會是。For example, the secret values aren't encrypted, but could be in the future.

啟用秘密儲存Enable secret storage

「秘密管理員」工具會針對儲存在使用者設定檔中的專案特定設定進行操作。The Secret Manager tool operates on project-specific configuration settings stored in your user profile.

若要使用使用者秘密,請 UserSecretsId 在 .csproj 檔案的中定義元素。 PropertyGroup .csprojTo use user secrets, define a UserSecretsId element within a PropertyGroup of the .csproj file. 的內部文字 UserSecretsId 是任意的,但對專案而言是唯一的。The inner text of UserSecretsId is arbitrary, but is unique to the project. 開發人員通常會產生的 GUID UserSecretsIdDevelopers typically generate a GUID for the UserSecretsId.

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
  <UserSecretsId>79a3edd0-2092-40a2-a04d-dcb46d5ca9ed</UserSecretsId>
</PropertyGroup>

提示

在 Visual Studio 中,以滑鼠右鍵按一下方案總管中的專案,然後從內容功能表中選取 [管理使用者秘密]。In Visual Studio, right-click the project in Solution Explorer, and select Manage User Secrets from the context menu. 此手勢會將已 UserSecretsId 填入 GUID 的元素新增至 .csproj檔案。This gesture adds a UserSecretsId element, populated with a GUID, to the .csproj file.

設定密碼Set a secret

定義由金鑰和其值組成的應用程式密碼。Define an app secret consisting of a key and its value. 此密碼與專案的值相關聯 UserSecretsIdThe secret is associated with the project's UserSecretsId value. 例如,從 .csproj檔案所在的目錄執行下列命令:For example, run the following command from the directory in which the .csproj file exists:

dotnet user-secrets set "Movies:ServiceApiKey" "12345"

在上述範例中,冒號表示 Movies 是具有屬性的物件常值 ServiceApiKeyIn the preceding example, the colon denotes that Movies is an object literal with a ServiceApiKey property.

秘密管理員工具也可以從其他目錄中使用。The Secret Manager tool can be used from other directories too. 使用 --project 選項來提供 .csproj檔案所在的檔案系統路徑。Use the --project option to supply the file system path at which the .csproj file exists. 例如:For example:

dotnet user-secrets set "Movies:ServiceApiKey" "12345" --project "C:\apps\WebApp1\src\WebApp1"

Visual Studio 中的 JSON 結構簡維JSON structure flattening in Visual Studio

Visual Studio 的 [管理使用者秘密] 手勢會在文字編輯器中開啟檔案secrets.jsVisual Studio's Manage User Secrets gesture opens a secrets.json file in the text editor. secrets.js的內容取代為要儲存的機碼值組。Replace the contents of secrets.json with the key-value pairs to be stored. 例如:For example:

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

JSON 結構會在透過或進行修改之後壓平合併 dotnet user-secrets remove dotnet user-secrets setThe JSON structure is flattened after modifications via dotnet user-secrets remove or dotnet user-secrets set. 例如,執行會折迭 dotnet user-secrets remove "Movies:ConnectionString" Movies 物件常值。For example, running dotnet user-secrets remove "Movies:ConnectionString" collapses the Movies object literal. 修改過的檔案如下所示:The modified file resembles the following:

{
  "Movies:ServiceApiKey": "12345"
}

設定多個秘密Set multiple secrets

您可以透過將 JSON 傳送至命令的方式來設定密碼批次 setA batch of secrets can be set by piping JSON to the set command. 在下列範例中,檔案內容上的input.js會以管道傳送至 set 命令。In the following example, the input.json file's contents are piped to the set command.

開啟命令 shell,然後執行下列命令:Open a command shell, and execute the following command:

type .\input.json | dotnet user-secrets set

存取秘密Access a secret

ASP.NET Core 設定 API提供秘密管理員密碼的存取權。The ASP.NET Core Configuration API provides access to Secret Manager secrets.

如果您的專案是以 .NET Framework 為目標,請安裝Microsoft.Extensions.Configuration。Usersecrets.xml NuGet 套件。If your project targets .NET Framework, install the Microsoft.Extensions.Configuration.UserSecrets NuGet package.

在 ASP.NET Core 2.0 或更新版本中,當專案呼叫 CreateDefaultBuilder 以預先設定的預設值來初始化主機的新實例時,就會自動在開發模式中新增使用者秘密設定來源。In ASP.NET Core 2.0 or later, the user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder to initialize a new instance of the host with preconfigured defaults. CreateDefaultBuilderAddUserSecrets當為時 EnvironmentName 呼叫 DevelopmentCreateDefaultBuilder calls AddUserSecrets when the EnvironmentName is Development:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

CreateDefaultBuilder 未呼叫時,請在函式中呼叫以明確新增使用者秘密設定來源 AddUserSecrets StartupWhen CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets in the Startup constructor. AddUserSecrets只有當應用程式在開發環境中執行時才會呼叫,如下列範例所示:Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", 
                     optional: false, 
                     reloadOnChange: true)
        .AddEnvironmentVariables();

    if (env.IsDevelopment())
    {
        builder.AddUserSecrets<Startup>();
    }

    Configuration = builder.Build();
}

您可以透過 API 來抓取使用者秘密 ConfigurationUser secrets can be retrieved via the Configuration API:

public class Startup
{
    private string _moviesApiKey = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        _moviesApiKey = Configuration["Movies:ServiceApiKey"];
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            var result = string.IsNullOrEmpty(_moviesApiKey) ? "Null" : "Not Null";
            await context.Response.WriteAsync($"Secret is {result}");
        });
    }
}

將秘密對應至 POCOMap secrets to a POCO

將整個物件常值對應至 POCO (具有屬性的簡單 .NET 類別),對於匯總相關屬性很有用。Mapping an entire object literal to a POCO (a simple .NET class with properties) is useful for aggregating related properties.

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

若要將上述密碼對應到 POCO,請使用 Configuration API 的物件圖形系結功能。To map the preceding secrets to a POCO, use the Configuration API's object graph binding feature. 下列程式碼會系結至自訂 MovieSettings POCO 並存取 ServiceApiKey 屬性值:The following code binds to a custom MovieSettings POCO and accesses the ServiceApiKey property value:

var moviesConfig = Configuration.GetSection("Movies")
                                .Get<MovieSettings>();
_moviesApiKey = moviesConfig.ServiceApiKey;

Movies:ConnectionStringMovies:ServiceApiKey 密碼會對應至中的個別屬性 MovieSettingsThe Movies:ConnectionString and Movies:ServiceApiKey secrets are mapped to the respective properties in MovieSettings:

public class MovieSettings
{
    public string ConnectionString { get; set; }

    public string ServiceApiKey { get; set; }
}

使用秘密取代字串String replacement with secrets

以純文字儲存密碼並不安全。Storing passwords in plain text is insecure. 例如,儲存在appsettings.js中的資料庫連接字串可能會包含指定使用者的密碼:For example, a database connection string stored in appsettings.json may include a password for the specified user:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;Password=pass123;MultipleActiveResultSets=true"
  }
}

更安全的方法是將密碼儲存為秘密。A more secure approach is to store the password as a secret. 例如:For example:

dotnet user-secrets set "DbPassword" "pass123"

Passwordappsettings.json的連接字串中移除索引鍵/值組。Remove the Password key-value pair from the connection string in appsettings.json. 例如:For example:

{
  "ConnectionStrings": {
    "Movies": "Server=(localdb)\\mssqllocaldb;Database=Movie-1;User Id=johndoe;MultipleActiveResultSets=true"
  }
}

您可以在物件的屬性上設定密碼的值 SqlConnectionStringBuilder Password ,以完成連接字串:The secret's value can be set on a SqlConnectionStringBuilder object's Password property to complete the connection string:

public class Startup
{
    private string _connection = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var builder = new SqlConnectionStringBuilder(
            Configuration.GetConnectionString("Movies"));
        builder.Password = Configuration["DbPassword"];
        _connection = builder.ConnectionString;
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync($"DB Connection: {_connection}");
        });
    }
}

列出秘密List the secrets

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets list

即會出現下列輸出:The following output appears:

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

在上述範例中,索引鍵名稱中的冒號代表secrets.js中的物件階層。In the preceding example, a colon in the key names denotes the object hierarchy within secrets.json.

移除單一秘密Remove a single secret

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets remove "Movies:ConnectionString"

應用程式在檔案上的secrets.js已修改為移除與機碼相關聯的機碼值組 MoviesConnectionStringThe app's secrets.json file was modified to remove the key-value pair associated with the MoviesConnectionString key:

{
  "Movies": {
    "ServiceApiKey": "12345"
  }
}

dotnet user-secrets list執行會顯示下列訊息:Running dotnet user-secrets list displays the following message:

Movies:ServiceApiKey = 12345

移除所有秘密Remove all secrets

假設應用程式的秘密 json檔案包含下列兩個秘密:Assume the app's secrets.json file contains the following two secrets:

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

.csproj檔案所在的目錄執行下列命令:Run the following command from the directory in which the .csproj file exists:

dotnet user-secrets clear

應用程式的所有使用者秘密已從檔案中的secrets.js刪除:All user secrets for the app have been deleted from the secrets.json file:

{}

dotnet user-secrets list執行會顯示下列訊息:Running dotnet user-secrets list displays the following message:

No secrets configured for this application.

其他資源Additional resources