次の方法で共有


ASP.NET Core での開発におけるアプリ シークレットの安全な保存

Note

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

作成者: Rick Anderson および Kirk Larkin

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

この記事では、開発用コンピューター上の ASP.NET Core アプリの機密データを管理する方法について説明します。 パスワードやその他の機密データをソース コードや構成ファイルに保存しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 運用シークレットには、Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure のテストシークレットと運用シークレットは、 Azure Key Vault 構成プロバイダーで格納および保護できます。

デプロイされたテスト アプリと運用アプリの認証の詳細については、「セキュリティで保護された認証フロー」をご覧ください。

.NET コンソール アプリでユーザー シークレットを使うには、こちらの GitHub イシューをご覧ください。

環境変数

環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。

個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json ファイルに DefaultConnection というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。

警告

環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。

: の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 たとえば、: の区切り記号は Bash では対応していません。 二重アンダースコア __ は、

  • すべてのプラットフォームで対応しています。
  • 自動でコロン : に置換されます。

シークレットマネージャー

Secret Manager ツールを使用すると、アプリケーションの開発中に機密データを保存できます。 このコンテキストでは、機密データはアプリのシークレットです。 アプリのシークレットは、プロジェクト ツリーとは別の場所に格納されます。 アプリのシークレットは、特定のプロジェクトに関連付けられるか、複数のプロジェクト間で共有されます。 アプリのシークレットは、ソース管理にはチェックインされません。

警告

シークレット マネージャー ツールでは保存されるシークレットは暗号化されないので、信頼されたストアとして扱わないでください。 それは開発のみを目的としたものです。 キーと値は、ユーザー プロファイルのディレクトリの JSON 構成ファイルに格納されます。

シークレット マネージャー ツールの動作

シークレット マネージャー ツールによって、値が格納される場所や方法などの実装の詳細が隠蔽されます。 これらの実装の詳細について知らなくても、このツールを使用できます。 値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。

ファイル システム パス:

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

上のファイル パスで、<user_secrets_id> はプロジェクト ファイルで指定されている UserSecretsId の値に置き換えてください。

シークレット マネージャー ツールによって保存されるデータの場所または形式に依存するコードを記述しないでください。 これらの実装の詳細は変更される可能性があります。 たとえば、シークレットの値は暗号化されません。

シークレット ストレージを有効にする

シークレット マネージャー ツールは、ユーザー プロファイルに格納されているプロジェクト固有の構成設定に基づいて動作します。

CLI の使用

シークレット マネージャー ツールには、init コマンドが含まれています。 ユーザー シークレットを使うには、プロジェクト ディレクトリで次のコマンドを実行します。

dotnet user-secrets init

上のコマンドによって、プロジェクト ファイルの PropertyGroup 内の UserSecretsId 要素が追加されます。 既定では、UserSecretsId の内部テキストは GUID です。 内部テキストは任意ですが、プロジェクトに固有です。

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

Visual Studio を使用する

Visual Studio のソリューション エクスプローラーでプロジェクトを右クリックし、コンテキスト メニューから [ユーザー シークレットの管理] を選びます。 これにより、UserSecretsId 要素がプロジェクト ファイルに追加されて、GUID が設定されます。

GenerateAssemblyInfofalse の場合

アセンブリ情報属性の生成が無効になっている場合は、手動で AssemblyInfo.csUserSecretsIdAttribute を追加します。 次に例を示します。

[assembly: UserSecretsId("your_user_secrets_id")]

UserSecretsId 属性を手動で AssemblyInfo.cs に追加する場合、UserSecretsId 値はプロジェクト ファイル内の値と一致する必要があります。

シークレットを設定する

キーとその値で構成されるアプリ シークレットを定義します。 シークレットは、プロジェクトの UserSecretsId の値に関連付けられます。 たとえば、プロジェクト ファイルが存在するディレクトリから次のコマンドを実行します。

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

前の例のコロンは、ServiceApiKeyMovies プロパティを持つオブジェクト リテラルであることを示しています。

シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --project オプションを使用して、プロジェクト ファイルが存在するファイル システム パスを指定します。 次に例を示します。

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

Visual Studio での JSON 構造のフラット化

Visual Studioの [ユーザー シークレットの管理] を選ぶと、テキスト エディターで secrets.json ファイルが開かれます。 secrets.json の内容を、格納するキーと値のペアに置き換えます。 次に例を示します。

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

JSON 構造体は、dotnet user-secrets remove または dotnet user-secrets set による変更後にフラット化されます。 たとえば、dotnet user-secrets remove "Movies:ConnectionString" を実行すると、Movies オブジェクト リテラルが折りたたまれます。 変更後のファイルは、次の JSON のようになります。

{
  "Movies:ServiceApiKey": "12345"
}

複数のシークレットを設定する

JSON を set コマンドにパイプすると、シークレットのバッチを設定できます。 次の例では、input.json ファイルのコンテンツが set コマンドにパイプされます。

コマンド シェルを開き、次のコマンドを実行します。

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

シークレットにアクセスする

シークレットにアクセスするには、次の手順を実行します。

  1. ユーザー シークレットの構成ソースを登録します
  2. Configuration API を使用してシークレットを読み取ります

ユーザー シークレットの構成ソースを登録する

ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .NET の Configuration API に登録されます。

dotnet new または Visual Studio で作成された ASP.NET Core の web アプリが、次のコードを生成します:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

WebApplication.CreateBuilder は、事前に構成された既定値を使用して WebApplicationBuilder クラスの新しいインスタンスを初期化します。 初期化された WebApplicationBuilder (builder) によって、既定の構成が指定され、EnvironmentNameDevelopment の場合に AddUserSecrets が呼び出されます。

Configuration API を使用してシークレットを読み取る

Movies:ServiceApiKey キーを読み取る次のような例を考えてみます。

Program.cs ファイル:

var builder = WebApplication.CreateBuilder(args);
var movieApiKey = builder.Configuration["Movies:ServiceApiKey"];

var app = builder.Build();

app.MapGet("/", () => movieApiKey);

app.Run();

Razor Pages ページ モデル:

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
    }
}

詳細については、「ASP.NET Core の構成」を参照してください。

シークレットを POCO にマップする

オブジェクト リテラル全体を POCO (プロパティを持つ単純な .NET クラス) にマップすると、関連するプロパティを集計するのに役立ちます。

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

前のシークレットを POCO にマップするには、.NET Configuration API のオブジェクト グラフ バインド機能を使います。 次のコードは、カスタム MovieSettings POCO にバインドされていて、ServiceApiKey プロパティ値にアクセスします。

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

シークレット Movies:ConnectionStringMovies:ServiceApiKey は、MovieSettings のそれぞれのプロパティにマップされます。

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

    public string ServiceApiKey { get; set; }
}

シークレットでの文字列の置換

プレーンテキストでのパスワードの保存は安全ではありません。 シークレットは、ソース コード リポジトリにチェックインされる可能性がある appsettings.jsonなどの構成ファイルに格納しないでください。

たとえば、appsettings.jsonに格納接続文字列データベースにパスワードを含めないようにする必要があります。 代わりに、パスワードをシークレットとして格納し、実行時に接続文字列にパスワードを含めます。 次に例を示します。

dotnet user-secrets set "DbPassword" "`<secret value>`"

前の例の <secret value> プレースホルダーをパスワード値に置き換えます。 SqlConnectionStringBuilder オブジェクトの Password プロパティにシークレットの値を設定して、接続文字列にパスワード値として含めます。

using System.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);

var conStrBuilder = new SqlConnectionStringBuilder(
        builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;

var app = builder.Build();

app.MapGet("/", () => connection);

app.Run();

シークレットの一覧を表示する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets list

次のような出力が表示されます。

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

前の例のキー名のコロンは、secrets.json 内のオブジェクト階層を示します。

1 つのシークレットを削除する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets remove "Movies:ConnectionString"

アプリの secrets.json ファイルが変更され、Movies:ConnectionString キーに関連付けられているキーと値のペアが削除されました。

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

dotnet user-secrets list では、次のメッセージが表示されます。

Movies:ServiceApiKey = 12345

すべてのシークレットを削除する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets clear

アプリのすべてのユーザー シークレットが、secrets.json ファイルから削除されました。

{}

dotnet user-secrets list を実行すると、次のメッセージが表示されます。

No secrets configured for this application.

Visual Studio でユーザー シークレットを管理する

Visual Studio でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。

[ユーザー シークレットの管理] が示されている Visual Studio

ASP.NET Framework から ASP.NET Core へのユーザー シークレットの移行

こちらの GitHub のイシューを参照してください。

非 Web アプリケーションのユーザー シークレット

Microsoft.NET.Sdk.Web をターゲットとするプロジェクトには、ユーザー シークレットのサポートが自動的に含まれます。 コンソール アプリケーションなど、Microsoft.NET.Sdk をターゲットとするプロジェクトの場合は、構成拡張機能とユーザー シークレット NuGet パッケージを明示的にインストールします。

PowerShell を使用して、次の操作を実行します。

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets

.NET CLI の使用

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets

パッケージがインストールされたら、Web アプリの場合と同じ方法でプロジェクトを初期化し、シークレットを設定します。 次の例は、キー "AppSecret" で設定されたシークレットの値を取得するコンソール アプリケーションを示しています。

using Microsoft.Extensions.Configuration;

namespace ConsoleApp;

class Program
{
    static void Main(string[] args)
    {
        IConfigurationRoot config = new ConfigurationBuilder()
            .AddUserSecrets<Program>()
            .Build();

        Console.WriteLine(config["AppSecret"]);
    }
}

その他のリソース

作成者: Rick AndersonKirk LarkinDaniel RothScott Addie

サンプル コードを表示またはダウンロードします (ダウンロード方法)。

この記事では、開発用コンピューター上の ASP.NET Core アプリの機密データを管理する方法について説明します。 パスワードやその他の機密データをソース コードや構成ファイルに保存しないでください。 運用環境のシークレットは、開発またはテストには使用しないでください。 アプリと一緒にシークレットを展開しないでください。 運用シークレットには、Azure Key Vault などの制御された手段を使用してアクセスする必要があります。 Azure のテストシークレットと運用シークレットは、 Azure Key Vault 構成プロバイダーで格納および保護できます。

テスト環境と運用環境の認証の詳細については、「 安全な認証フロー」を参照してください。

環境変数

環境変数は、コードやローカル構成ファイルにアプリのシークレットを格納しないようにするために使用されます。 環境変数によって、以前に指定したすべての構成ソースの構成値がオーバーライドされます。

個別のユーザー アカウントのセキュリティが有効になっている ASP.NET Core Webアプリについて考えます。 既定のデータベース接続文字列は、プロジェクトの appsettings.json ファイルに DefaultConnection というキーで格納されています。 既定の接続文字列は、ユーザー モードで実行され、パスワードを必要としない LocalDB 用です。 アプリの展開の間に、DefaultConnection キーの値を環境変数の値でオーバーライドできます。 環境変数には、機密資格情報との完全な接続文字列を格納できます。

警告

環境変数は、通常、暗号化されていないプレーンテキストで格納されます。 コンピューターまたはプロセスが侵害された場合、信頼されていないパーティーが環境変数にアクセスできるようになります。 ユーザー シークレットの漏えいを防ぐ追加手段が必要になる場合があります。

: の区切り記号は、すべてのプラットフォームの環境変数階層キーには対応していません。 たとえば、: の区切り記号は Bash では対応していません。 二重アンダースコア __ は、

  • すべてのプラットフォームで対応しています。
  • 自動でコロン : に置換されます。

シークレットマネージャー

Secret Manager ツールを使用すると、アプリケーションの開発中に機密データを保存できます。 このコンテキストでは、機密データはアプリのシークレットです。 アプリのシークレットは、プロジェクト ツリーとは別の場所に格納されます。 アプリのシークレットは、特定のプロジェクトに関連付けられるか、複数のプロジェクト間で共有されます。 アプリのシークレットは、ソース管理にはチェックインされません。

警告

シークレット マネージャー ツールでは保存されるシークレットは暗号化されないので、信頼されたストアとして扱わないでください。 それは開発のみを目的としたものです。 キーと値は、ユーザー プロファイルのディレクトリの JSON 構成ファイルに格納されます。

シークレット マネージャー ツールの動作

シークレット マネージャー ツールによって、値が格納される場所や方法などの実装の詳細が隠蔽されます。 これらの実装の詳細について知らなくても、このツールを使用できます。 値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。

ファイル システム パス:

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

上のファイル パスで、<user_secrets_id> はプロジェクト ファイルで指定されている UserSecretsId の値に置き換えてください。

シークレット マネージャー ツールによって保存されるデータの場所または形式に依存するコードを記述しないでください。 これらの実装の詳細は変更される可能性があります。 たとえば、シークレットの値は暗号化されませんが、将来は暗号化される可能性があります。

シークレット ストレージを有効にする

シークレット マネージャー ツールは、ユーザー プロファイルに格納されているプロジェクト固有の構成設定に基づいて動作します。

シークレット マネージャー ツールには、.NET Core SDK 3.0.100 以降の init コマンドが含まれています。 ユーザー シークレットを使うには、プロジェクト ディレクトリで次のコマンドを実行します。

dotnet user-secrets init

上のコマンドによって、プロジェクト ファイルの PropertyGroup 内の UserSecretsId 要素が追加されます。 既定では、UserSecretsId の内部テキストは GUID です。 内部テキストは任意ですが、プロジェクトに固有です。

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

Visual Studio のソリューション エクスプローラーでプロジェクトを右クリックし、コンテキスト メニューから [ユーザー シークレットの管理] を選びます。 これにより、UserSecretsId 要素がプロジェクト ファイルに追加されて、GUID が設定されます。

シークレットを設定する

キーとその値で構成されるアプリ シークレットを定義します。 シークレットは、プロジェクトの UserSecretsId の値に関連付けられます。 たとえば、プロジェクト ファイルが存在するディレクトリから次のコマンドを実行します。

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

前の例のコロンは、ServiceApiKeyMovies プロパティを持つオブジェクト リテラルであることを示しています。

シークレット マネージャー ツールは、他のディレクトリからも使用できます。 --project オプションを使用して、プロジェクト ファイルが存在するファイル システム パスを指定します。 次に例を示します。

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

Visual Studio での JSON 構造のフラット化

Visual Studioの [ユーザー シークレットの管理] を選ぶと、テキスト エディターで secrets.json ファイルが開かれます。 secrets.json の内容を、格納するキーと値のペアに置き換えます。 次に例を示します。

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

JSON 構造体は、dotnet user-secrets remove または dotnet user-secrets set による変更後にフラット化されます。 たとえば、dotnet user-secrets remove "Movies:ConnectionString" を実行すると、Movies オブジェクト リテラルが折りたたまれます。 変更後のファイルは、次の JSON のようになります。

{
  "Movies:ServiceApiKey": "12345"
}

複数のシークレットを設定する

JSON を set コマンドにパイプすると、シークレットのバッチを設定できます。 次の例では、input.json ファイルのコンテンツが set コマンドにパイプされます。

コマンド シェルを開き、次のコマンドを実行します。

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

シークレットにアクセスする

シークレットにアクセスするには、次の手順を実行します。

  1. ユーザー シークレットの構成ソースを登録します
  2. Configuration API を使用してシークレットを読み取ります

ユーザー シークレットの構成ソースを登録する

ユーザー シークレットの構成プロバイダーにより、適切な構成ソースが .NET の Configuration API に登録されます。

プロジェクトで CreateDefaultBuilder が呼び出されると、ユーザー シークレットの構成ソースが開発モードで自動的に追加されます。 EnvironmentNameDevelopment のときは、CreateDefaultBuilder によって AddUserSecrets が呼び出されます。

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

CreateDefaultBuilder が呼び出されないときは、ConfigureAppConfigurationAddUserSecrets を呼び出して、ユーザー シークレットの構成ソースを明示的に追加します。 次の例で示すように、アプリが開発環境で実行されている場合にのみ、AddUserSecrets を呼び出します。

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

Configuration API を使用してシークレットを読み取る

ユーザー シークレットの構成ソースが登録されている場合は、.NET Configuration API でシークレットを読み取ることができます。 コンストラクターの挿入を使って、.NET Configuration API にアクセスできます。 Movies:ServiceApiKey キーを読み取る次のような例を考えてみます。

スタートアップ クラス:

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 Pages ページ モデル:

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 ページの構成にアクセスする」をご覧ください。

シークレットを POCO にマップする

オブジェクト リテラル全体を POCO (プロパティを持つ単純な .NET クラス) にマップすると、関連するプロパティを集計するのに役立ちます。

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

前のシークレットを POCO にマップするには、.NET Configuration API のオブジェクト グラフ バインド機能を使います。 次のコードは、カスタム MovieSettings POCO にバインドされていて、ServiceApiKey プロパティ値にアクセスします。

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

シークレット Movies:ConnectionStringMovies:ServiceApiKey は、MovieSettings のそれぞれのプロパティにマップされます。

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

    public string ServiceApiKey { get; set; }
}

シークレットでの文字列の置換

プレーンテキストでのパスワードの保存は安全ではありません。 シークレットは、ソース コード リポジトリにチェックインされる可能性がある appsettings.jsonなどの構成ファイルに格納しないでください。

たとえば、appsettings.jsonに格納接続文字列データベースにパスワードを含めないようにする必要があります。 代わりに、パスワードをシークレットとして格納し、実行時に接続文字列にパスワードを含めます。 次に例を示します。

dotnet user-secrets set "DbPassword" "<secret value>"

前の例の <secret value> プレースホルダーをパスワード値に置き換えます。 SqlConnectionStringBuilder オブジェクトの Password プロパティにシークレットの値を設定して、接続文字列にパスワード値として含めます。

using System.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);

var conStrBuilder = new SqlConnectionStringBuilder(
        builder.Configuration.GetConnectionString("Movies"));
conStrBuilder.Password = builder.Configuration["DbPassword"];
var connection = conStrBuilder.ConnectionString;

var app = builder.Build();

app.MapGet("/", () => connection);

app.Run();

シークレットの一覧を表示する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets list

次のような出力が表示されます。

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

前の例のキー名のコロンは、secrets.json 内のオブジェクト階層を示します。

1 つのシークレットを削除する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets remove "Movies:ConnectionString"

アプリの secrets.json ファイルが変更され、MoviesConnectionString キーに関連付けられているキーと値のペアが削除されました。

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

dotnet user-secrets list では、次のメッセージが表示されます。

Movies:ServiceApiKey = 12345

すべてのシークレットを削除する

アプリの secrets.json ファイルに、次の 2 つのシークレットが含まれているとします。

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

プロジェクト ファイルが存在するディレクトリから、次のコマンドを実行します。

dotnet user-secrets clear

アプリのすべてのユーザー シークレットが、secrets.json ファイルから削除されました。

{}

dotnet user-secrets list を実行すると、次のメッセージが表示されます。

No secrets configured for this application.

Visual Studio でユーザー シークレットを管理する

Visual Studio でユーザー シークレットを管理するには、ソリューション エクスプローラーでプロジェクトを右クリックして、 [ユーザー シークレットの管理] を選びます。

[ユーザー シークレットの管理] が示されている Visual Studio

ASP.NET Framework から ASP.NET Core へのユーザー シークレットの移行

こちらの GitHub のイシューを参照してください。

非 Web アプリケーションのユーザー シークレット

Microsoft.NET.Sdk.Web をターゲットとするプロジェクトには、ユーザー シークレットのサポートが自動的に含まれます。 コンソール アプリケーションなど、Microsoft.NET.Sdk をターゲットとするプロジェクトの場合は、構成拡張機能とユーザー シークレット NuGet パッケージを明示的にインストールします。

PowerShell を使用して、次の操作を実行します。

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.UserSecrets

.NET CLI の使用

dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.UserSecrets

パッケージがインストールされたら、Web アプリの場合と同じ方法でプロジェクトを初期化し、シークレットを設定します。 次の例は、キー "AppSecret" で設定されたシークレットの値を取得するコンソール アプリケーションを示しています。

using Microsoft.Extensions.Configuration;

namespace ConsoleApp;

class Program
{
    static void Main(string[] args)
    {
        IConfigurationRoot config = new ConfigurationBuilder()
            .AddUserSecrets<Program>()
            .Build();

        Console.WriteLine(config["AppSecret"]);
    }
}

その他のリソース