在 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 how to manage sensitive data for 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 金鑰保存庫等受控方式來存取生產秘密。Instead, production secrets should be accessed through a controlled means like environment variables or Azure Key Vault. 您可以透過 Azure Key Vault 設定提供者儲存及保護 Azure 測試與生產祕密。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.json DefaultConnectionA 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 hides 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 file in the local machine's user profile folder:

檔案系統路徑:File system path:

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

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

請勿撰寫相依于使用 Secret Manager 工具儲存的資料位置或格式的程式碼。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

上述命令會 UserSecretsId 在專案檔的中加入 PropertyGroup 專案。The preceding command adds a UserSecretsId element within a PropertyGroup of the project 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 填入的專案加入至專案檔。This gesture adds a UserSecretsId element, populated with a GUID, to the project 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. 例如,從專案檔所在的目錄中執行下列命令:For example, run the following command from the directory in which the project 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 可以使用選項來提供專案檔所在的檔案系統路徑。Use the --project option to supply the file system path at which the project 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. 修改過的檔案類似下列 JSON:The modified file resembles the following JSON:

{
  "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

若要存取秘密,請完成下列步驟:To access a secret, complete the following steps:

  1. 註冊使用者秘密設定來源Register the user secrets configuration source
  2. 透過設定 API 讀取秘密Read the secret via the Configuration API

註冊使用者秘密設定來源Register the user secrets configuration source

使用者密碼設定 提供者 會使用 .NET 設定 API來註冊適當的設定來源。The user secrets configuration provider registers the appropriate configuration source with the .NET Configuration API.

當專案呼叫時,使用者秘密設定來源會自動加入至開發模式 CreateDefaultBuilderThe user secrets configuration source is automatically added in Development mode when the project calls CreateDefaultBuilder. 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未呼叫時,請在中呼叫以明確地新增使用者秘密設定來源 AddUserSecrets ConfigureAppConfigurationWhen CreateDefaultBuilder isn't called, add the user secrets configuration source explicitly by calling AddUserSecrets in ConfigureAppConfiguration. AddUserSecrets只有當應用程式在開發環境中執行時才呼叫,如下列範例所示:Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new HostBuilder()
            .ConfigureAppConfiguration((hostContext, builder) =>
            {
                // Add other providers for JSON, etc.

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

透過設定 API 讀取秘密Read the secret via the Configuration API

如果已登錄使用者秘密設定來源,則 .NET 設定 API 可以讀取秘密。If the user secrets configuration source is registered, the .NET Configuration API can read the secrets. 您可以使用「函式插入」來取得 .NET 設定 API 的存取權。Constructor injection can be used to gain access to the .NET Configuration API. 請考慮下列讀取金鑰的範例 Movies:ServiceApiKeyConsider the following examples of reading the Movies:ServiceApiKey key:

Startup 類別:Startup class:

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}");
        });
    }
}

Razor 頁面頁面模型:Razor Pages page model:

public class IndexModel : PageModel
{
    private readonly IConfiguration _config;

    public IndexModel(IConfiguration config)
    {
        _config = config;
    }

    public void OnGet()
    {
        var moviesApiKey = _config["Movies:ServiceApiKey"];

        // call Movies service with the API key
    }
}

如需詳細資訊,請參閱 啟動及[存取設定] Razor 頁面中存取設定。For more information, see Access configuration in Startup and Access configuration in Razor Pages.

將秘密對應至 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.

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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,請使用 .NET 設定 API 的 物件圖形 系結功能。To map the preceding secrets to a POCO, use the .NET 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.json 可能包含指定使用者的密碼: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"

Password從的連接字串中移除機碼值組 appsettings.jsonRemove 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;

        // code omitted for brevity
    }

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

列出秘密List the secrets

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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 how to manage sensitive data for 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 金鑰保存庫等受控方式來存取生產秘密。Instead, production secrets should be accessed through a controlled means like environment variables or Azure Key Vault. 您可以透過 Azure Key Vault 設定提供者儲存及保護 Azure 測試與生產祕密。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.json DefaultConnectionA 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 hides 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 file in the local machine's user profile folder:

檔案系統路徑:File system path:

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

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

請勿撰寫相依于使用 Secret Manager 工具儲存的資料位置或格式的程式碼。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 專案檔中定義 PropertyGroup 專案。To use user secrets, define a UserSecretsId element within a PropertyGroup of the project 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 填入的專案加入至專案檔。This gesture adds a UserSecretsId element, populated with a GUID, to the project 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. 例如,從專案檔所在的目錄中執行下列命令:For example, run the following command from the directory in which the project 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 可以使用選項來提供專案檔所在的檔案系統路徑。Use the --project option to supply the file system path at which the project 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. 修改過的檔案類似下列 JSON:The modified file resembles the following JSON:

{
  "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

設定 API 會提供使用者密碼的存取權。The Configuration API provides access to user 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 或更新版本中,當專案呼叫時,使用者秘密設定來源會自動加入至開發模式 CreateDefaultBuilderIn ASP.NET Core 2.0 or later, the user secrets configuration source is automatically added in development mode when the project calls CreateDefaultBuilder. 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();
}

您可以透過 .NET 設定 API 來抓取使用者密碼:User secrets can be retrieved via the .NET 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.

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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,請使用 .NET 設定 API 的 物件圖形 系結功能。To map the preceding secrets to a POCO, use the .NET 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.json 可能包含指定使用者的密碼: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; $CREDENTIAL_PLACEHOLDER$;MultipleActiveResultSets=true"
  }
}

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

dotnet user-secrets set "DbPassword" "pass123"

Password從的連接字串中移除機碼值組 appsettings.jsonRemove 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

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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

假設應用程式的 secrets.js 檔案包含下列兩個秘密: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"
  }
}

從專案檔所在的目錄中執行下列命令:Run the following command from the directory in which the project 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