Поделиться через


Безопасное хранение секретов приложений в разработке в ASP.NET Core

Note

Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.

Warning

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.

Авторы: Рик Андерсон (Rick Anderson) и Кирк Ларкин (Kirk Larkin)

Просмотреть или скачать образец кода (описание загрузки)

В этой статье объясняется, как управлять конфиденциальными данными для приложения ASP.NET Core на компьютере разработки. Никогда не хранить пароли или другие конфиденциальные данные в исходном коде или файлах конфигурации. Не следует использовать секреты рабочей среды для разработки или тестирования. Секретные данные не следует развертывать с приложением. Доступ к рабочим секретам должен осуществляться с помощью контролируемых средств, таких как Azure Key Vault. Тестовые и рабочие секреты Azure могут храниться и защищаться с помощью поставщика конфигурации Azure Key Vault.

Дополнительные сведения о проверке подлинности для развернутых тестовых и рабочих приложений см. в разделе "Безопасные потоки проверки подлинности".

Чтобы использовать секреты пользователей в консольном приложении .NET, обратитесь к этому вопросу на GitHub.

Переменные среды

Переменные среды используются для предотвращения хранения секретов приложения в коде или в локальных файлах конфигурации. Переменные среды переопределяют значения конфигурации для всех ранее указанных источников конфигурации.

Рассмотрим веб-приложение ASP.NET Core, в котором включена безопасность отдельных учетных записей . Строка подключения по умолчанию для базы данных включена в файл проекта appsettings.json с ключом DefaultConnection. По умолчанию строка подключения используется для LocalDB, который выполняется в пользовательском режиме и не требует пароля. Во время развертывания приложения DefaultConnection значение ключа можно переопределить значением переменной среды. Переменная среды может хранить полную строку соединения с конфиденциальными учетными данными.

Warning

Переменные среды обычно хранятся в простом незашифрованном тексте. Если компьютер или процесс скомпрометированы, переменные среды могут быть доступны ненадежным сторонам. Могут потребоваться дополнительные меры по предотвращению раскрытия секретов пользователей.

Разделитель : не работает с иерархическими ключами переменных среды на всех платформах. Например, : разделитель не поддерживается Bash. Двойные подчеркивания, __ поддерживаются всеми платформами и автоматически заменяются двоеточием :.

Менеджер секретов

Средство Secret Manager хранит конфиденциальные данные во время разработки приложений. В этом контексте конфиденциальные данные — это секрет приложения. Секреты приложений хранятся в отдельном расположении от дерева проекта. Секреты приложения связаны с определенным проектом или используются совместно в нескольких проектах. Секреты приложения не помещаются в систему контроля версий.

Warning

Средство диспетчера секретов не шифрует сохраненные секреты и не должно рассматриваться как доверенное хранилище. Это только для целей разработки. Ключи и значения хранятся в файле конфигурации JSON в каталоге профилей пользователя.

Как работает средство диспетчера секретов

Средство диспетчера секретов скрывает сведения о реализации, такие как место и способ хранения значений. Средство можно использовать, не зная этих сведений о реализации. Значения хранятся в JSON-файле в папке профиля пользователя локального компьютера:

Путь к файловой системе:

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

В предыдущих путях к файлам замените <user_secrets_id> значением UserSecretsId, указанным в файле проекта.

Не записывайте код, зависящий от расположения или формата данных, сохраненных с помощью средства Диспетчера секретов. Эти сведения о реализации могут измениться. Например, значения секретов не шифруются.

Включение хранилища секретов

Средство Диспетчера секретов работает с параметрами конфигурации для конкретного проекта, хранящимися в профиле пользователя.

Использование CLI

Инструмент Secret Manager включает команду init. Чтобы использовать секреты пользователей, выполните следующую команду в каталоге проекта:

dotnet user-secrets init

Предыдущая команда добавляет UserSecretsId элемент в PropertyGroup файл проекта. По умолчанию внутренний текст UserSecretsId — это GUID. Внутренний текст является произвольным, но является уникальным для проекта.

Конфигурация свойства UserSecretsId MSBuild в файле проекта приложения.

Использование Visual Studio

В Visual Studio щелкните проект правой кнопкой мыши в Обозреватель решений и выберите пункт "Управление секретами пользователей" в контекстном меню. Этот жест добавляет в файл проекта элемент UserSecretsId, заполненный GUID.

Если GenerateAssemblyInfo имеет значение false

Если создание атрибутов сведений о сборке отключено, добавьте UserSecretsIdAttribute и AssemblyInfo.cs вручную. Рассмотрим пример.

[assembly: UserSecretsId("your_user_secrets_id")]

При добавлении атрибута UserSecretsIdAssemblyInfo.csUserSecretsId вручную значение должно соответствовать значению в файле проекта.

Установка секрета

Определите секрет приложения, состоящий из ключа и его значения. Секрет связан со значением проекта UserSecretsId . Например, выполните следующую команду из каталога, в котором существует файл проекта:

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

В предыдущем примере двоеточие указывает на то, что Movies — это объектный литерал со свойством ServiceApiKey.

Средство диспетчера секретов также можно использовать из других каталогов. Используйте опцию --project, чтобы указать путь в файловой системе, где находится файл проекта. Рассмотрим пример.

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

Выравнивание структуры JSON в Visual Studio

Visual Studio, используя функцию "Управление секретами пользователей", открывает файл в текстовом редакторе. Замените содержимое 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. Чтение секрета с помощью API конфигурации

Зарегистрируйте источник конфигурации секретов пользователя

Поставщик конфигурации секретов пользователя регистрирует соответствующий источник конфигурации с помощью API конфигурации .NET.

Веб-приложения ASP.NET Core, созданные с помощью dotnet new или Visual Studio, создают следующий код:

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

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

app.Run();

WebApplication.CreateBuilder инициализирует новый экземпляр класса WebApplicationBuilder с предварительно настроенными значениями по умолчанию. Инициализированный WebApplicationBuilder (builder) предоставляет конфигурацию по умолчанию и вызывает AddUserSecrets, когда EnvironmentName является Development.

Прочтите секрет через 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 содержит следующие два секрета:

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

Чтобы сопоставить предыдущие секреты с POCO, используйте функцию привязки графа объектов конфигурации .NET. Следующий код привязывается к пользовательскому MovieSettings POCO и обращается к значению ServiceApiKey свойства:

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

Movies:ConnectionString и Movies: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> заполнитель в предыдущем примере значением пароля. Задайте значение секрета для свойства Password объекта SqlConnectionStringBuilder, чтобы использовать его в качестве значения пароля в строке подключения.

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 содержит следующие два секрета:

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

Удаление одного секрета

Предположим, что файл приложения secrets.json содержит следующие два секрета:

{
  "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 содержит следующие два секрета:

{
  "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 показывает управление секретами пользователей

Перенос секретов пользователей из платформы .NET Framework в ASP.NET Core

Также см. эту проблему в GitHub.

Секреты пользователей в не веб-приложениях

Проекты, нацеленные на 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

После установки пакетов инициализируйте проект и задайте секреты так же, как для веб-приложения. В следующем примере показано консольное приложение, которое извлекает значение секрета, заданного ключом 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"]);
    }
}

Дополнительные ресурсы

Рик Андерсон, Кирк Ларкин, Даниэль Рот и Скотт Адди

Просмотреть или скачать образец кода (описание загрузки)

В этой статье объясняется, как управлять конфиденциальными данными для приложения ASP.NET Core на компьютере разработки. Никогда не хранить пароли или другие конфиденциальные данные в исходном коде или файлах конфигурации. Не следует использовать секреты рабочей среды для разработки или тестирования. Секретные данные не следует развертывать с приложением. Доступ к рабочим секретам должен осуществляться с помощью контролируемых средств, таких как Azure Key Vault. Тестовые и рабочие секреты Azure могут храниться и защищаться с помощью поставщика конфигурации Azure Key Vault.

Дополнительные сведения о проверке подлинности для тестовых и рабочих сред см. в разделе "Безопасные потоки проверки подлинности".

Переменные среды

Переменные среды используются для предотвращения хранения секретов приложения в коде или в локальных файлах конфигурации. Переменные среды переопределяют значения конфигурации для всех ранее указанных источников конфигурации.

Рассмотрим веб-приложение ASP.NET Core, в котором включена безопасность отдельных учетных записей пользователей . Строка подключения по умолчанию для базы данных включена в файл проекта appsettings.json с ключом DefaultConnection. По умолчанию строка подключения используется для LocalDB, который выполняется в пользовательском режиме и не требует пароля. Во время развертывания приложения DefaultConnection значение ключа можно переопределить значением переменной среды. Переменная среды может хранить полную строку соединения с конфиденциальными учетными данными.

Warning

Переменные среды обычно хранятся в простом незашифрованном тексте. Если компьютер или процесс скомпрометированы, переменные среды могут быть доступны ненадежным сторонам. Могут потребоваться дополнительные меры по предотвращению раскрытия секретов пользователей.

Разделитель : не работает с иерархическими ключами переменных среды на всех платформах. Например, : разделитель не поддерживается Bash. Двойные подчеркивания, __ поддерживаются всеми платформами и автоматически заменяются двоеточием :.

Менеджер секретов

Средство Secret Manager хранит конфиденциальные данные во время разработки приложений. В этом контексте конфиденциальные данные — это секрет приложения. Секреты приложений хранятся в отдельном расположении от дерева проекта. Секреты приложения связаны с определенным проектом или используются совместно в нескольких проектах. Секреты приложения не помещаются в систему контроля версий.

Warning

Средство диспетчера секретов не шифрует сохраненные секреты и не должно рассматриваться как доверенное хранилище. Это только для целей разработки. Ключи и значения хранятся в файле конфигурации JSON в каталоге профилей пользователя.

Как работает средство диспетчера секретов

Средство диспетчера секретов скрывает сведения о реализации, такие как место и способ хранения значений. Средство можно использовать, не зная этих сведений о реализации. Значения хранятся в JSON-файле в папке профиля пользователя локального компьютера:

Путь к файловой системе:

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

В предыдущих путях к файлам замените <user_secrets_id> значением UserSecretsId, указанным в файле проекта.

Не записывайте код, зависящий от расположения или формата данных, сохраненных с помощью средства Диспетчера секретов. Эти сведения о реализации могут измениться. Например, секретные значения не шифруются, но могут быть в будущем.

Включение хранилища секретов

Средство Диспетчера секретов работает с параметрами конфигурации для конкретного проекта, хранящимися в профиле пользователя.

Инструмент управления секретами включает команду init в пакете SDK для .NET Core версии 3.0.100 или более поздней. Чтобы использовать секреты пользователей, выполните следующую команду в каталоге проекта:

dotnet user-secrets init

Предыдущая команда добавляет UserSecretsId элемент в PropertyGroup файл проекта. По умолчанию внутренний текст 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"

В предыдущем примере двоеточие указывает, что Movies является объектным литералом со свойством ServiceApiKey.

Инструмент управления секретами можно использовать и из других каталогов. Используйте параметр --project, чтобы указать путь к каталогу, в котором находится файл проекта. Рассмотрим пример.

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

Выравнивание структуры JSON в Visual Studio

Управление секретами пользователей в 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. Чтение секрета с помощью API конфигурации

Зарегистрируйте источник конфигурации секретов пользователя

Поставщик конфигурации секретов пользователя регистрирует соответствующий источник конфигурации в API конфигурации .NET.

Источник конфигурации секретов пользователя автоматически добавляется в режиме разработки при вызове CreateDefaultBuilder проекта. CreateDefaultBuilder вызывает AddUserSecrets когда EnvironmentName это Development

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

Если CreateDefaultBuilder не вызывается, добавьте источник конфигурации секретов пользователя явным образом путем вызова AddUserSecrets в ConfigureAppConfiguration. Вызовите AddUserSecrets только в том случае, если приложение работает в Development среде, как показано в следующем примере:

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 настройки

Если зарегистрирован источник конфигурации секретов пользователя, API конфигурации .NET может считывать секреты. Constructor injection можно использовать для получения доступа к API конфигурации .NET. Рассмотрим следующие примеры чтения 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
    }
}

Дополнительные сведения см. в разделе "Конфигурация доступа в Startup" и "Конфигурация доступа в Razor страницах".

Сопоставление секретов с POCO

Сопоставление всего литерала объекта с POCO (простой класс .NET со свойствами) полезно для агрегирования связанных свойств.

Предположим, что файл приложения secrets.json содержит следующие два секрета:

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

Чтобы сопоставить предыдущие секреты с POCO, используйте функцию привязки графа объекта конфигурации .NET. Следующий код привязывается к пользовательскому MovieSettings POCO и обращается к значению ServiceApiKey свойства:

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

Movies:ConnectionString и Movies: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 содержит следующие два секрета:

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

Удаление одного секрета

Предположим, что файл приложения secrets.json содержит следующие два секрета:

{
  "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 содержит следующие два секрета:

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

Секреты пользователей в не веб-приложениях

Проекты, нацеленные на 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

После установки пакетов инициализируйте проект и задайте секреты так же, как для веб-приложения. В следующем примере показано консольное приложение, которое извлекает значение секрета, заданного ключом 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"]);
    }
}

Дополнительные ресурсы