Cadenas de conexión y archivos de configuración

La incrustación de cadenas de conexión en el código de la aplicación puede producir vulnerabilidades en la seguridad y problemas de mantenimiento. Las cadenas de conexión sin cifrar compiladas en el código fuente de una aplicación se pueden ver con la herramienta Ildasm.exe (Desensamblador de IL). Además, si la cadena de conexión cambia en algún momento, será necesario compilar de nuevo la aplicación. Por estas razones, se recomienda almacenar las cadenas de conexión en un archivo de configuración de la aplicación.

Trabajar con archivos de configuración de la aplicación

Los archivos de configuración de la aplicación contienen valores específicos de una aplicación determinada. Por ejemplo, una aplicación ASP.NET puede tener uno o varios archivos web.config y una aplicación Windows puede tener un archivo app.config opcional. Los archivos de configuración comparten elementos comunes, aunque su nombre y ubicación varían en función del host de la aplicación.

Sección connectionStrings

Las cadenas de conexión se pueden almacenar como pares clave-valor en la sección connectionStrings del elemento configuration en el archivo de configuración de una aplicación. Los elementos secundarios incluyen add, clear y remove.

El siguiente fragmento del archivo de configuración muestra el esquema y la sintaxis para almacenar una cadena de conexión. El atributo name es un nombre que se proporciona para identificar de forma única una cadena de conexión, de forma que se pueda recuperar en tiempo de ejecución. providerName es el nombre invariable del proveedor de datos de .NET Framework registrado en el archivo 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>  

Nota:

Puede guardar parte de la cadena de conexión en un archivo de configuración y usar la clase DbConnectionStringBuilder para completarla en tiempo de ejecución. Esto resulta útil en escenarios en los que no se conocen los elementos de la cadena de conexión por anticipado o cuando no desea guardar información confidencial en un archivo de configuración. Para obtener más información, vea Generadores de cadenas de conexión.

Uso de archivos de configuración externos

Los archivos de configuración externos son archivos independientes que contienen un fragmento de un archivo de configuración compuesto de una sola sección. El archivo de configuración principal hace referencia al archivo de configuración externo. El almacenamiento de la sección connectionStrings en un archivo físicamente independiente resulta útil en situaciones en las que es posible que se editen las cadenas de conexión después de implementar la aplicación. Por ejemplo, si se modifican los archivos de configuración, ASP.NET reinicia de forma predeterminada el dominio de la aplicación, lo que provoca la pérdida de la información de estado. Sin embargo, la modificación de un archivo de configuración externo no provoca el reinicio de la aplicación. Los archivos de configuración externos no se limitan a ASP.NET; también se pueden utilizar en aplicaciones Windows. Además, la seguridad y permisos de acceso a los archivos se pueden usar para restringir el acceso a los archivos de configuración externos. El trabajo con archivos de configuración externos en tiempo de ejecución es transparente y no requiere código especial.

Para almacenar las cadenas de conexión en un archivo de configuración externo, cree un archivo independiente que contenga únicamente la sección connectionStrings. No incluya elementos, secciones ni atributos adicionales. En este ejemplo se muestra la sintaxis de un archivo de configuración externo.

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

En el archivo de configuración principal de la aplicación, use el atributo configSource para especificar el nombre completo y la ubicación del archivo externo. En este ejemplo se hace referencia a un archivo de configuración externo denominado connections.config.

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

Recuperar cadenas de conexión en tiempo de ejecución

.NET Framework 2.0 incorpora nuevas clases en el espacio de nombres System.Configuration para simplificar la recuperación de las cadenas de conexión de los archivos de configuración en tiempo de ejecución. La cadena de conexión se puede recuperar mediante programación con el nombre de la cadena o el nombre de proveedor.

Nota:

El archivo machine.config también contiene una sección connectionStrings, donde se encuentran las cadenas de conexión que usa Visual Studio. Al recuperar cadenas de conexión mediante el nombre del proveedor del archivo app.config en una aplicación Windows, primero se cargan las cadenas de conexión del archivo machine.config y, a continuación, las entradas de app.config. Si se agrega clear inmediatamente después del elemento connectionStrings, se quitarán todas las referencias heredadas de la estructura de datos en memoria, de forma que solo se tendrán en cuenta las cadenas de conexión definidas en el archivo app.config local.

Trabajar con clases de configuración

A partir de .NET Framework 2.0, se usa el elemento ConfigurationManager al trabajar con archivos de configuración en el equipo local, reemplazando al elemento en desuso ConfigurationSettings. WebConfigurationManager se usa para trabajar con archivos de configuración de ASP.NET. Esta característica se ha diseñado para trabajar con archivos de configuración en un servidor web y permite el acceso mediante programación a secciones del archivo de configuración como system.web.

Nota:

El acceso a los archivos de configuración en tiempo de ejecución requiere la concesión de permisos al llamador; los permisos necesarios dependen del tipo de aplicación, del archivo de configuración y de la ubicación. Para obtener más información, vea Utilizar las clases Configuration y WebConfigurationManager para las aplicaciones ASP.NET, o bien ConfigurationManager para las aplicaciones Windows.

Puede usar ConnectionStringSettingsCollection para recuperar cadenas de conexión de archivos de configuración de aplicación. Esta clase contiene una colección de objetos ConnectionStringSettings, cada uno de los cuales representa una única entrada en la sección connectionStrings. Sus propiedades se asignan a los atributos de cadenas de conexión, lo que permite recuperar una cadena de conexión mediante la especificación de su nombre o del nombre del proveedor.

Propiedad Descripción
Name Nombre de la cadena de conexión. Se asigna al atributo name.
ProviderName Nombre completo del proveedor. Se asigna al atributo providerName.
ConnectionString La cadena de conexión. Se asigna al atributo connectionString.

Ejemplo: mostrar todas las cadenas de conexión

Este ejemplo recorre en iteración ConnectionStringSettingsCollection y muestra las propiedades ConnectionStringSettings.Name, ConnectionStringSettings.ProviderName y ConnectionStringSettings.ConnectionString en la ventana de la consola.

Nota:

System.Configuration.dll no se incluye en todos los tipos de proyectos y es posible que deba establecer una referencia a este elemento para usar las clases de configuración. El nombre y la ubicación de un archivo de configuración de aplicación determinado varían en función del tipo de aplicación y del proceso de hospedaje.

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

Ejemplo: recuperar una cadena de conexión por su nombre

El siguiente ejemplo muestra cómo recuperar una cadena de conexión de un archivo de configuración mediante la especificación del nombre. El código crea un objeto ConnectionStringSettings, de forma que el parámetro de entrada proporcionado coincida con el nombre de ConnectionStrings. Si no se encuentra una coincidencia de nombre, la función devuelve null (Nothing en 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

Ejemplo: recuperar una cadena de conexión por el nombre de proveedor

En este ejemplo se muestra cómo recuperar una cadena de conexión mediante la especificación del nombre invariable de proveedor con el formato Sistema.Datos.NombreDelProveedor. El código recorre en iteración ConnectionStringSettingsCollection y devuelve la cadena de conexión del primer valor de ProviderName encontrado. Si no se encuentra el nombre del proveedor, la función devuelve null (Nothing en 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

Cifrar secciones del archivo de configuración mediante una configuración protegida

En ASP.NET 2.0 se incorporó una característica nueva denominada configuración protegida, que permite cifrar la información confidencial en un archivo de configuración. Si bien se ha diseñado principalmente para ASP.NET, la configuración protegida también se puede usar para cifrar secciones del archivo de configuración en aplicaciones Windows. Para obtener una descripción detallada de las funciones de configuración protegida, vea Cifrar información de configuración mediante una configuración protegida.

En el fragmento de archivo de configuración siguiente se muestra la sección connectionStrings después de haberse cifrado. En la sección configProtectionProvider se especifica el proveedor de configuración protegida que se usa para cifrar y descifrar las cadenas de conexión. En la sección EncryptedData se incluye el texto cifrado.

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

Cuando se recupera la cadena de conexión cifrada en tiempo de ejecución, .NET Framework usa el proveedor especificado para descifrar CipherValue y que así esté disponible para la aplicación. No es necesario escribir ningún código adicional para administrar el proceso de descifrado.

Proveedores de configuración protegida

Los proveedores de configuración protegida se registran en la sección configProtectedData del archivo machine.config en el equipo local, como se muestra en el fragmento siguiente, donde se pueden ver los dos proveedores de configuración protegida que proporciona .NET Framework. Los valores que se muestran se han truncado para facilitar la lectura.

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

Puede configurar otros proveedores de configuración protegida si los agrega al archivo machine.config. Asimismo, puede crear su propio proveedor de configuración protegida heredando de la clase base abstracta ProtectedConfigurationProvider. En la tabla siguiente se describen los dos archivos de configuración incluidos en .NET Framework.

Proveedor Descripción
RsaProtectedConfigurationProvider Usa el algoritmo de cifrado RSA para cifrar y descifrar datos. Los algoritmos RSA se pueden usar para el cifrado de clave pública y para firmas digitales. También se conoce como cifrado de "clave pública" o asimétrico, ya que usa dos claves diferentes. Puede usar la Herramienta de registro de IIS en ASP.NET (aspnet_regiis.exe) para cifrar secciones de un archivo Web.config y administrar las claves de cifrado. ASP.NET descifra el archivo de configuración cuando lo procesa. La identidad de la aplicación ASP.NET debe tener acceso de lectura a la clave de cifrado utilizada para cifrar y descifrar las secciones cifradas.
DpapiProtectedConfigurationProvider Usa la API de protección de datos (DPAPI) de Windows para cifrar y descifrar las secciones de configuración. Usa los servicios criptográficos integrados de Windows y se puede configurar para la protección específica de equipo o para la protección específica de cuenta de usuario. La protección específica de equipo resulta útil cuando varias aplicaciones del mismo servidor deben compartir información. La protección específica de cuenta de usuario se puede utilizar para los servicios que se ejecutan con una identidad de usuario concreta, como un entorno de hospedaje compartido. Cada aplicación se ejecuta con una identidad independiente que limita el acceso a recursos como los archivos y las bases de datos.

Ambos proveedores proporcionan cifrado de datos de alta seguridad. No obstante, si prevé usar el mismo archivo de configuración de cifrado en varios servidores como, por ejemplo, una granja de servidores web, solo RsaProtectedConfigurationProvider permite exportar las claves de cifrado usadas para cifrar los datos e importarlas a otro servidor. Para obtener más información, vea Importar y exportar contenedores de claves RSA con configuración protegida.

Uso de clases de configuración

El espacio de nombres System.Configuration proporciona clases para trabajar con valores de configuración mediante programación. La clase ConfigurationManager proporciona acceso a los archivos de configuración de equipo, aplicación y usuario. Si va a crear una aplicación ASP.NET, puede usar la clase WebConfigurationManager, que proporciona las mismas funciones a la vez que permite tener acceso a configuración única de las aplicaciones ASP.NET, como la que se encuentra en <system.web>.

Nota:

El espacio de nombres System.Security.Cryptography contiene clases que proporcionan opciones adicionales para cifrar y descifrar datos. Use estas clases si requiere servicios criptográficos que no están disponibles cuando se usa la configuración protegida. Algunas de estas clases son contenedores de Microsoft CryptoAPI no administrado, mientras que otras son simplemente implementaciones administradas. Para más información, vea Servicios criptográficos.

Ejemplo de App.config

En este ejemplo se muestra cómo alternar el cifrado de la sección connectionStrings de un archivo app.config para una aplicación Windows. En este ejemplo, el procedimiento recibe el nombre de la aplicación como argumento, por ejemplo, "MyApplication.exe". Después, el archivo app.config se cifra y se copia en la carpeta que contiene el ejecutable con el nombre "MyApplication.exe.config".

Nota:

La cadena de conexión solo se puede descifrar en el equipo donde se ha cifrado.

El código usa el método OpenExeConfiguration para abrir el archivo app.config y editarlo; el método GetSection devuelve la sección connectionStrings. A continuación, el código comprueba la propiedad IsProtected y llama a ProtectSection para cifrar la sección si no está cifrada. Para descifrar la sección se llama al método UnprotectSection. El método Save completa la operación y guarda los cambios.

Nota:

Para ejecutar el código, debe establecer una referencia al archivo System.Configuration.dll del proyecto.

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

Ejemplo de Web.config

Este ejemplo usa el método OpenWebConfiguration de WebConfigurationManager. Observe que en este caso puede indicar la ruta de acceso relativa al archivo Web.config mediante una tilde. El código requiere una referencia a la clase 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

Para obtener más información sobre cómo proteger las aplicaciones de ASP.NET, vea Protección de sitios web ASP.NET.

Vea también