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


Строки подключения и файлы конфигурации

Внедрение строк соединения в код приложения может привести к появлению уязвимых мест в системе безопасности и проблем с обслуживанием. Незашифрованные строки подключения, скомпилированные в исходный код приложения, можно просматривать с помощью средства Ildasm.exe (IL Disassembler). Кроме того, после изменения строки соединения необходимо перекомпилировать приложение. По этим причинам рекомендуется хранить строки соединения в файле конфигурации приложения.

Внимание

Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Если вы подключаетесь к Azure SQL, управляемые удостоверения для ресурсов Azure являются рекомендуемым методом аутентификации.

Файлы конфигурации приложений

Файлы конфигурации приложения содержат настройки, относящиеся к отдельному приложению. Например, приложение ASP.NET может иметь один или несколько файлов web.config, а приложение Windows — дополнительный файл app.config. В файлах конфигурации присутствуют общие элементы, хотя имя и расположение любого файла конфигурации в значительной степени зависят от того, где размещается приложение.

Раздел connectionStrings

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

Следующий фрагмент файла конфигурации демонстрирует схему и синтаксис хранения строки соединения. Атрибут name — это имя, которое вы предоставляете для уникальной идентификации строки подключения, чтобы ее можно было получить во время выполнения. Это providerName инвариантное имя поставщика данных .NET Framework, зарегистрированного в файле machine.config.

<?xml version='1.0' encoding='utf-8'?>
  <configuration>
    <connectionStrings>
      <clear />
      <add name="Name"
       providerName="System.Data.ProviderName"
       connectionString="Valid Connection String;" />
    </connectionStrings>
  </configuration>

Примечание.

Вы можете сохранить часть строки подключения в файле конфигурации и использовать DbConnectionStringBuilder класс для его завершения во время выполнения. Это полезно в сценариях, когда элементы строка подключения не знаются заранее или когда вы не хотите сохранять конфиденциальную информацию в файле конфигурации. Дополнительные сведения см. в статье Connection String Builders (Построители строк подключения).

Использование внешних файлов конфигурации

Внешние файлы конфигурации представляют собой отдельные файлы, каждый из которых содержит фрагмент файла конфигурации, состоящий из одного раздела. В таком случае основной файл конфигурации ссылается на внешний файл конфигурации. connectionStrings Хранение раздела в физическом отдельном файле полезно в ситуациях, когда строки подключения могут быть изменены после развертывания приложения. Например, в ASP.NET по умолчанию после изменения файлов конфигурации осуществляется перезапуск домена приложения, что приводит к потере сведений о состоянии. Но изменение внешнего файла конфигурации не вызывает перезапуск приложения. Возможность применения внешних файлов конфигурации не ограничивается ASP.NET; их можно также использовать в приложениях Windows. Кроме того, для ограничения доступа к внешним файлам конфигурации могут использоваться средства обеспечения безопасности доступа к файлам и разрешения. Работа с внешними файлами конфигурации во время выполнения является прозрачной и не требует специального кода.

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

<connectionStrings>
  <add name="Name"
   providerName="System.Data.ProviderName"
   connectionString="Valid Connection String;" />
</connectionStrings>

В файле конфигурации основного приложения атрибут configSource используется, чтобы указать полное имя и расположение внешнего файла. В следующем примере применяется ссылка на внешний файл конфигурации с именем connections.config.

<?xml version='1.0' encoding='utf-8'?>
<configuration>
    <connectionStrings configSource="connections.config"/>
</configuration>

Получение строк подключения во время выполнения

.NET Framework 2.0 представил новые классы в System.Configuration пространстве имен, чтобы упростить получение строк подключения из файлов конфигурации во время выполнения. Предусмотрена возможность получить строку соединения программным путем по ее имени или по имени поставщика.

Примечание.

Файл machine.config также содержит connectionStrings раздел, содержащий строки подключения, используемые Visual Studio. При извлечении строк подключения по имени поставщика из файла app.config в Windows-приложении, строки подключения из machine.config загружаются первыми, а затем записи из app.config. Добавление clear сразу после элемента connectionStrings удаляет все унаследованные ссылки из структуры данных в памяти, поэтому учитываются только строки подключения, определенные в локальном файле app.config.

Работа с классами конфигурации

Начиная с платформа .NET Framework 2.0, ConfigurationManager используется при работе с файлами конфигурации на локальном компьютере, заменив устаревший ConfigurationSettings класс. WebConfigurationManager служит для работы с файлами конфигурации ASP.NET. Он создан для работы с файлами конфигурации веб-сервера и предоставляет программный доступ к разделам файла конфигураций, например system.web.

Примечание.

Для доступа к файлам конфигурации во время выполнения требуется предоставление разрешений вызывающему объекту; необходимые разрешения зависят от типа приложения, файла конфигурации и расположения. Дополнительные сведения см. в приложениях для ASP.NET WebConfigurationManager и приложениях для Windows ConfigurationManager.

Для получения строк соединения из файлов конфигурации приложения используется ConnectionStringSettingsCollection. Он содержит коллекцию ConnectionStringSettings объектов, каждая из которых представляет одну запись в connectionStrings разделе. Его свойства сопоставляются с атрибутами строки подключения, что позволяет получить строку подключения, указав имя или имя поставщика.

Свойство Описание
Name Имя строки соединения. Сопоставляется с атрибутом name .
ProviderName Полностью квалифицированное имя поставщика. Сопоставляется с атрибутом providerName .
ConnectionString Строка подключения. Сопоставляется с атрибутом connectionString .

Пример: Перечисление всех строк подключения

В этом примере выполняется итерация ConnectionStringSettingsCollection и отображаются свойства ConnectionStringSettings.Name, ConnectionStringSettings.ProviderName и ConnectionStringSettings.ConnectionString в окне консоли.

Примечание.

System.Configuration.dll не входит во все типы проектов и может потребоваться задать ссылку на нее, чтобы использовать классы конфигурации. Имя и расположение файла конфигурации определенного приложения зависит от типа приложения и процесса размещения.

using System.Configuration;

static class Program
{
    static void Main()
    {
        GetConnectionStrings();
        Console.ReadLine();
    }

    static void GetConnectionStrings()
    {
        ConnectionStringSettingsCollection settings =
            ConfigurationManager.ConnectionStrings;

        foreach (ConnectionStringSettings cs in settings)
        {
            Console.WriteLine(cs.Name);
            Console.WriteLine(cs.ProviderName);
            Console.WriteLine(cs.ConnectionString);
        }
    }
}
Imports System.Configuration

Class Program
    Shared Sub Main()
        GetConnectionStrings()
        Console.ReadLine()
    End Sub

    Private Shared Sub GetConnectionStrings()

        Dim settings As ConnectionStringSettingsCollection = _
            ConfigurationManager.ConnectionStrings

        If Not settings Is Nothing Then
            For Each cs As ConnectionStringSettings In settings
                Console.WriteLine(cs.Name)
                Console.WriteLine(cs.ProviderName)
                Console.WriteLine(cs.ConnectionString)
            Next
        End If
    End Sub
End Class

Пример: Извлечение строки подключения по имени

Данный пример демонстрирует способ получения строки соединения из файла конфигурации путем указания ее имени. Код создает объект ConnectionStringSettings, сопоставляя указанный входной параметр с именем ConnectionStrings. Если совпадающее имя не найдено, функция возвращает значение null (Nothing в Visual Basic).

// Retrieves a connection string by name.
// Returns null if the name is not found.
static string? GetConnectionStringByName(string name)
{
    // Look for the name in the connectionStrings section.
    ConnectionStringSettings? settings =
        ConfigurationManager.ConnectionStrings[name];

    // If found, return the connection string (otherwise return null)
    return settings?.ConnectionString;
}
' Retrieves a connection string by name.
' Returns Nothing if the name is not found.
Private Shared Function GetConnectionStringByName( _
    ByVal name As String) As String

    ' Assume failure
    Dim returnValue As String = Nothing

    ' Look for the name in the connectionStrings section.
    Dim settings As ConnectionStringSettings = _
       ConfigurationManager.ConnectionStrings(name)

    ' If found, return the connection string.
    If Not settings Is Nothing Then
        returnValue = settings.ConnectionString
    End If

    Return returnValue
End Function

Пример. Получение строки подключения по имени поставщика

В этом примере демонстрируется способ получения строки подключения путем указания неизменяемого имени поставщика в формате System.Data.ProviderName. В коде выполняется итерация по ConnectionStringSettingsCollection и происходит возврат строки соединения для первого найденного ProviderName. Если имя поставщика не найдено, функция возвращает значение null (Nothing в Visual Basic).

// Retrieve a connection string by specifying the providerName.
// Assumes one connection string per provider in the config file.
static string? GetConnectionStringByProvider(string providerName)
{
    // Get the collection of connection strings.
    ConnectionStringSettingsCollection? settings =
        ConfigurationManager.ConnectionStrings;

    // Walk through the collection and return the first
    // connection string matching the providerName.
    if (settings != null)
    {
        foreach (ConnectionStringSettings cs in settings)
        {
            if (cs.ProviderName == providerName)
            {
                return cs.ConnectionString;
            }
        }
    }
    return null;
}
' Retrieve a connection string by specifying the providerName.
' Assumes one connection string per provider in the config file.
Private Shared Function GetConnectionStringByProvider( _
    ByVal providerName As String) As String

    'Return Nothing on failure.
    Dim returnValue As String = Nothing

    ' Get the collection of connection strings.
    Dim settings As ConnectionStringSettingsCollection = _
        ConfigurationManager.ConnectionStrings

    ' Walk through the collection and return the first 
    ' connection string matching the providerName.
    If Not settings Is Nothing Then
        For Each cs As ConnectionStringSettings In settings
            If cs.ProviderName = providerName Then
                returnValue = cs.ConnectionString
                Exit For
            End If
        Next
    End If

    Return returnValue
End Function

Шифрование разделов файла конфигурации с помощью защищенной конфигурации

В ASP.NET 2.0 появилась новая возможность, защищенная конфигурация, с помощью которой можно шифровать в файле конфигурации конфиденциальную информацию. Защищенная конфигурация разрабатывалась в первую очередь для ASP.NET, но ее можно также использовать для шифрования разделов файлов конфигурации в приложениях Windows.

В следующем фрагменте файла конфигурации показаны разделы connectionStrings после их шифрования. Используемый поставщик конфигурации configProtectionProvider, защищающий строки подключения, отвечает за их шифрование и расшифровку. Раздел EncryptedData содержит текст шифра.

<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
    <CipherData>
      <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAH2... </CipherValue>
    </CipherData>
  </EncryptedData>
</connectionStrings>

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

Поставщики защищенной конфигурации

Защищенные поставщики конфигурации регистрируются в configProtectedData разделе файлаmachine.config на локальном компьютере, как показано в следующем фрагменте, где показаны два защищенных поставщика конфигураций, предоставляемые платформой .NET Framework. Показанные значения были усечены для удобства чтения.

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
  <providers>
    <add name="RsaProtectedConfigurationProvider"
      type="System.Configuration.RsaProtectedConfigurationProvider" />
    <add name="DataProtectionConfigurationProvider"
      type="System.Configuration.DpapiProtectedConfigurationProvider" />
  </providers>
</configProtectedData>

Можно назначить дополнительные поставщики защищенной конфигурации, добавляя их в файл machine.config. Кроме того, можно создать собственный поставщик защищенной конфигурации путем наследования от абстрактного базового класса ProtectedConfigurationProvider. В следующей таблице описаны два файла конфигурации, включенные в платформа .NET Framework.

Поставщик Описание
RsaProtectedConfigurationProvider Использует алгоритм RSA для шифрования и расшифровки данных. Алгоритм RSA можно использовать для шифрования с открытым ключом и цифровых сигнатур. Он также известен как алгоритм с «открытым ключом» или алгоритм асимметричного шифрования, поскольку в нем используется два разных ключа. Для шифрования разделов в файле Web.config и управления ключами шифрования можно использовать средство регистрации служб IIS ASP.NET (Aspnet_regiis.exe). ASP.NET расшифровывает файл конфигурации при обработке файла. Учетная запись приложения ASP.NET должна иметь права на чтение ключа шифрования, который используется для шифрования и расшифровки зашифрованных разделов.
DpapiProtectedConfigurationProvider Использует API-интерфейс защиты данных (DPAPI) для шифрования разделов конфигурации. Он использует встроенные службы шифрования Windows и может быть настроен для защиты отдельных компьютеров или отдельных учетных записей пользователей. Защиту отдельных компьютеров удобно использовать для нескольких приложений на одном сервере, которым требуется совместное использование данных. Специфичную для учетной записи пользователя защиту можно использовать со службами, выполняемыми с определенной идентификацией пользователя, например с общей средой хостинга. Каждое приложение выполняется с отдельным удостоверением, которое ограничивает доступ к ресурсам, например к файлам и базам данных.

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

Использование классов конфигурации

Пространство имен System.Configuration предоставляет классы для программной обработки параметров конфигурации. Класс ConfigurationManager обеспечивает доступ к компьютеру, приложению и пользовательским файлам конфигурации. При создании приложения ASP.NET можно использовать класс WebConfigurationManager, который предоставляет те же функциональные возможности и одновременно позволяет обращаться к уникальным настройкам приложений ASP.NET, в частности, в файле <system.web>.

Примечание.

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

Пример App.config

В этом примере показано, как переключать шифрование connectionStrings раздела в файлеapp.config для приложения Windows. В этом примере процедура принимает имя приложения в качестве аргумента, например, «MyApplication.exe». Затем файл app.config шифруется и копируется в папку, содержащую исполняемый файл под именем "MyApplication.exe.config".

Код использует OpenExeConfiguration метод для открытия файлаapp.config для редактирования, а GetSection метод возвращает connectionStrings раздел. Затем код проверяет свойство IsProtected, вызывая метод ProtectSection для шифрования раздела, если он не зашифрован. Метод UnprotectSection вызывается для расшифровки раздела. (Строка подключения можно расшифровать только на компьютере, на котором он был зашифрован.) Метод Save завершает операцию и сохраняет изменения.

Чтобы код работал, необходимо добавить ссылку на System.Configuration.dll в ваш проект.

Внимание

Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Если вы подключаетесь к Azure SQL, управляемые удостоверения для ресурсов Azure являются рекомендуемым методом аутентификации.

static void ToggleConfigEncryption(string exeFile)
{
    // Get the application path needed to obtain
    // the application configuration file.

    // Takes the executable file name without the
    // .config extension.
    var exePath = exeFile.Replace(".config", "");

    try
    {
        // Open the configuration file and retrieve
        // the connectionStrings section.
        Configuration config = ConfigurationManager.
            OpenExeConfiguration(exePath);

        var section =
            config.GetSection("connectionStrings")
            as ConnectionStringsSection;

        if (section != null)
        {
            if (section.SectionInformation.IsProtected)
            {
                // Remove encryption.
                section.SectionInformation.UnprotectSection();
            }
            else
            {
                // Encrypt the section.
                section.SectionInformation.ProtectSection(
                    "DataProtectionConfigurationProvider");
            }
        }
        // Save the current configuration.
        config.Save();

        Console.WriteLine($"Protected={section?.SectionInformation.IsProtected}");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Shared Sub ToggleConfigEncryption(ByVal exeConfigName As String)
    ' Takes the executable file name without the
    ' .config extension.
    Try
        ' Open the configuration file and retrieve 
        ' the connectionStrings section.
        Dim config As Configuration = ConfigurationManager. _
            OpenExeConfiguration(exeConfigName)

        Dim section As ConnectionStringsSection = DirectCast( _
            config.GetSection("connectionStrings"), _
            ConnectionStringsSection)

        If section.SectionInformation.IsProtected Then
            ' Remove encryption.
            section.SectionInformation.UnprotectSection()
        Else
            ' Encrypt the section.
            section.SectionInformation.ProtectSection( _
              "DataProtectionConfigurationProvider")
        End If

        ' Save the current configuration.
        config.Save()

        Console.WriteLine("Protected={0}", _
        section.SectionInformation.IsProtected)

    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try
End Sub

Пример Web.config

В этом примере используется метод OpenWebConfiguration класса WebConfigurationManager. В этом случае можно указать относительный путь к файлу web.config с помощью тильды. В коде должна быть ссылка на класс System.Web.Configuration.

static void ToggleWebEncrypt()
{
    // Open the Web.config file.
    Configuration config = WebConfigurationManager.
        OpenWebConfiguration("~");

    // Get the connectionStrings section.
    var section =
        config.GetSection("connectionStrings")
        as ConnectionStringsSection;

    // Toggle encryption.
    if (section.SectionInformation.IsProtected)
    {
        section.SectionInformation.UnprotectSection();
    }
    else
    {
        section.SectionInformation.ProtectSection(
            "DataProtectionConfigurationProvider");
    }

    // Save changes to the Web.config file.
    config.Save();
}
Shared Sub ToggleWebEncrypt()
    ' Open the Web.config file.
    Dim config As Configuration = WebConfigurationManager. _
      OpenWebConfiguration("~")

    ' Get the connectionStrings section.
    Dim section As ConnectionStringsSection = DirectCast( _
        config.GetSection("connectionStrings"), _
        ConnectionStringsSection)

    ' Toggle encryption.
    If section.SectionInformation.IsProtected Then
        section.SectionInformation.UnprotectSection()
    Else
        section.SectionInformation.ProtectSection( _
          "DataProtectionConfigurationProvider")
    End If

    ' Save changes to the Web.config file.
    config.Save()
End Sub

Дополнительные сведения о защите приложений ASP.NET см. в статье Защита веб-сайтов ASP.NET.

См. также