Строки подключения и файлы конфигурации
Внедрение строк соединения в код приложения может привести к появлению уязвимых мест в системе безопасности и проблем с обслуживанием. Незашифрованные строки подключения, скомпилированные в исходный код приложения, можно просматривать с помощью средства Ildasm.exe (IL Disassembler). Кроме того, после изменения строки соединения необходимо перекомпилировать приложение. По этим причинам рекомендуется хранить строки соединения в файле конфигурации приложения.
Внимание
Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Если вы подключаетесь к SQL Azure, управляемые удостоверения для ресурсов Azure — это рекомендуемый метод проверки подлинности.
Файлы конфигурации приложений
Файлы конфигурации приложения содержат настройки, относящиеся к отдельному приложению. Например, приложение ASP.NET может иметь один или несколько файлов web.config, а приложение Windows — дополнительный файл app.config. В файлах конфигурации присутствуют общие элементы, хотя имя и расположение любого файла конфигурации в значительной степени зависят от того, где размещается приложение.
Раздел connectionStrings
Строки подключения могут храниться в виде пар "ключ/значение" в разделе connectionStrings элемента configuration файла конфигурации приложения. Дочерние элементы включают add, clear и remove.
Следующий фрагмент файла конфигурации демонстрирует схему и синтаксис хранения строки соединения. Атрибут 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. Добавление ясно сразу после того, как элемент connectionStrings удаляет все унаследованные ссылки из структуры данных в памяти, чтобы считаться только строка подключения, определенные в локальном файле app.config.
Работа с классами конфигурации
Начиная с платформа .NET Framework 2.0, ConfigurationManager используется при работе с файлами конфигурации на локальном компьютере, заменив устаревший ConfigurationSettings класс. WebConfigurationManager служит для работы с файлами конфигурации ASP.NET. Он создан для работы с файлами конфигурации веб-сервера и предоставляет программный доступ к разделам файла конфигураций, например system.web.
Примечание.
Вызывающему объекту для доступа к файлам конфигурации во время выполнения должны быть предоставлены разрешения. Требуемые разрешения зависят от типа приложения, файла конфигурации и расположения. Дополнительные сведения см. в ASP.NET WebConfigurationManager приложениях и ConfigurationManager приложениях Windows.
Для получения строк соединения из файлов конфигурации приложения используется ConnectionStringSettingsCollection. Этот объект содержит коллекцию объектов ConnectionStringSettings, каждый из которых представляет одну запись в разделе connectionStrings. Его свойства сопоставляются с атрибутами строк соединения, что позволяет получить строку соединения, указав имя строки или имя поставщика.
Свойство | Description |
---|---|
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.
Provider | Description |
---|---|
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
на проект.
Внимание
Корпорация Майкрософт рекомендует использовать самый безопасный поток проверки подлинности. Если вы подключаетесь к SQL Azure, управляемые удостоверения для ресурсов 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={0}",
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.