Stringhe di connessione e file di configurazione

Se le stringhe di connessione vengono incorporate nel codice dell'applicazione, è possibile che si verifichino vulnerabilità della sicurezza e problemi di manutenzione. Le stringhe di connessione non crittografate compilate nel codice sorgente di un'applicazione possono essere visualizzate tramite lo strumento Ildasm.exe (Disassembler IL). Inoltre, se la stringa di connessione viene modificata, è necessario ricompilare l'applicazione. Per questi motivi, si consiglia di archiviare le stringhe di connessione in un file di configurazione dell'applicazione.

Utilizzo dei file di configurazione delle applicazioni

I file di configurazione delle applicazioni contengono impostazioni specifiche di una determinata applicazione. Ad esempio, un'applicazione ASP.NET può includere uno o più file web.config, mentre un'applicazione Windows può includere un file app.config facoltativo. I file di configurazione condividono elementi comuni, anche se il nome e il percorso variano a seconda dell'host dell'applicazione.

Sezione connectionStrings

Le stringhe di connessione possono essere archiviate come coppie chiave/valore nella sezione connectionStrings dell'elemento configuration di un file di configurazione dell'applicazione. Gli elementi figlio includono add, clear e remove.

Nel frammento di file di configurazione seguente sono illustrati lo schema e la sintassi per l'archiviazione di una stringa di connessione. L'attributo name corrisponde al nome specificato per identificare in modo univoco una connessione, in modo che possa essere recuperato in fase di esecuzione. L'attributo providerName è il nome invariabile del provider di dati .NET Framework, registrato nel file 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

È possibile salvare parte di una stringa di connessione in un file di configurazione e usare la classe DbConnectionStringBuilder per completarlo in fase di esecuzione. Questa funzione è utile nelle situazioni in cui non si conoscono in anticipo gli elementi della stringa di connessione o quando non si desidera salvare informazioni sensibili in un file di configurazione. Per altre informazioni, vedere Compilatori di stringhe di connessione.

Uso di file di configurazione esterni

I file di configurazione esterni sono file distinti che contengono un frammento di un file di configurazione costituito da un'unica sezione. Al file di configurazione esterno viene quindi fatto riferimento dal file di configurazione principale. L'archiviazione della sezione connectionStrings in un file fisicamente distinto risulta utile nelle situazioni in cui le stringhe di connessione potrebbero essere modificate dopo la distribuzione dell'applicazione. Ad esempio, il comportamento ASP.NET standard prevede il riavvio di un dominio di applicazione quando i file di configurazione vengono modificati, con la conseguenza che le informazioni sullo stato vanno perse. Tuttavia, la modifica di un file di configurazione esterno non provoca un riavvio dell'applicazione. Oltre che in ASP.NET, i file di configurazione esterni possono essere usati anche nelle applicazioni Windows. È possibile inoltre usare la sicurezza e le autorizzazioni di accesso ai file per limitare l'accesso ai file di configurazione esterni. L'uso di file di configurazione esterni in fase di esecuzione è trasparente e non richiede codice speciale.

Per archiviare le stringhe di connessione in un file di configurazione esterno, creare un file distinto che contenga solo la sezione connectionStrings. Non includere altri elementi, sezioni o attributi. Questo esempio illustra la sintassi di un file di configurazione esterno.

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

Nel file di configurazione principale dell'applicazione usare l'attributo configSource per specificare il nome completo e il percorso del file esterno. In questo esempio si fa riferimento a un file di configurazione esterno denominato connections.config.

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

Recupero delle stringhe di connessione in fase di esecuzione

In .NET Framework 2.0 sono state introdotte nuove classi nello spazio dei nomi System.Configuration per semplificare il recupero delle stringhe di connessione dai file di configurazione in fase di esecuzione. È possibile recuperare una stringa di connessione a livello di codice in base al nome o al nome del provider.

Nota

Il file machine.config include anche una sezione connectionStrings contenente le stringhe di connessione usate da Visual Studio. Se le stringhe di connessione vengono recuperate in base al nome del provider dal file app.config in un'applicazione Windows, vengono caricate dapprima le stringhe di connessione presenti in machine.config e quindi le voci di app.config. L'aggiunta di clear immediatamente dopo l'elemento connectionStrings consente di rimuovere tutti i riferimenti ereditati dalla struttura dati in memoria, in modo che vengano considerate solo le stringhe di connessione definite nel file app.config locale.

Utilizzo delle classi di configurazione

A partire da .NET Framework 2.0, quando si usano i file di configurazione nel computer locale, viene usato ConfigurationManager al posto dell'oggetto ConfigurationSettings deprecato. Per i file di configurazione di ASP.NET, viene usato WebConfigurationManager, progettato per essere usato con i file di configurazione in un server Web, che consente l'accesso a livello di codice alle sezioni del file di configurazione come system.web.

Nota

L'accesso ai file di configurazione in fase di esecuzione richiede la concessione di autorizzazioni al chiamante. Le autorizzazioni necessarie dipendono dal tipo di applicazione, dal file di configurazione e dal percorso. Per altre informazioni, vedere Utilizzo delle classi di configurazione e WebConfigurationManager per le applicazioni ASP.NET e ConfigurationManager per le applicazioni Windows.

È possibile usare ConnectionStringSettingsCollection per recuperare le stringhe di connessione dai file di configurazione dell'applicazione. Contiene una raccolta di oggetti ConnectionStringSettings, ognuno dei quali rappresenta una singola voce della sezione connectionStrings. Le proprietà sono mappate ad attributi di stringa di connessione, consentendo di recuperare una stringa di connessione in base al nome o al nome del provider.

Proprietà Descrizione
Name Nome della stringa di connessione. È mappata all'attributo name.
ProviderName Nome completo del provider. È mappata all'attributo providerName.
ConnectionString La stringa di connessione. È mappata all'attributo connectionString.

Esempio: elenco di tutte le stringhe di connessione

In questo esempio viene eseguita l'iterazione di ConnectionStringSettingsCollection e vengono visualizzate le proprietà ConnectionStringSettings.Name, ConnectionStringSettings.ProviderName e ConnectionStringSettings.ConnectionString nella finestra della console.

Nota

System.Configuration.dll non è incluso in tutti i tipi di progetto e potrebbe essere necessario impostare un riferimento a questo file per usare le classi di configurazione. Il nome e il percorso di un determinato file di configurazione dell'applicazione variano in base al tipo di applicazione e al processo di hosting.

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

Esempio: recupero di una stringa di connessione in base al nome

In questo esempio viene illustrato come recuperare una stringa di connessione da un file di configurazione specificandone il nome. Nel codice viene creato un oggetto ConnectionStringSettings e il parametro di input specificato viene associato al nome ConnectionStrings. Se non viene trovato alcun nome corrispondente, la funzione restituisce null (Nothing in 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

Esempio: recupero di una stringa di connessione in base al nome del provider

In questo esempio viene illustrato come recuperare una stringa di connessione specificando il nome invariabile del provider nel formato System.Data.ProviderName. Il codice consente di scorrere ConnectionStringSettingsCollection e restituisce la stringa di connessione per il primo ProviderName trovato. Se il nome del provider non viene trovato, la funzione restituisce null (Nothing in 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

Crittografia di sezioni dei file di configurazione tramite configurazione protetta

In ASP.NET 2.0 è stata introdotta una nuova funzionalità, denominata configurazione protetta, che consente di crittografare le informazioni riservate in un file di configurazione. Sebbene sia stata progettata principalmente per ASP.NET, questa funzionalità può essere usata anche per crittografare sezioni dei file di configurazione nelle applicazioni Windows. Per una descrizione dettagliata delle funzionalità della configurazione protetta, vedere Crittografia delle informazioni di configurazione utilizzando la configurazione protetta.

Nel frammento di file di configurazione seguente è illustrata la sezione connectionStrings dopo la crittografia. Nella sezione configProtectionProvider è specificato il provider di configurazione protetta usato per crittografare e decrittografare le stringhe di connessione. La sezione EncryptedData contiene il testo crittografato.

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

Quando la stringa di connessione crittografata viene recuperata in fase di esecuzione, in .NET Framework viene usato il provider specificato per decrittografare CipherValue e renderlo disponibile per l'applicazione. Non è necessario scrivere codice aggiuntivo per gestire il processo di decrittografia.

Provider di configurazione protetta

I provider di configurazione protetta sono registrati nella sezione configProtectedData del file machine.config nel computer locale, come illustrato nel frammento seguente, in cui sono indicati i due provider di configurazione protetta disponibili in .NET Framework. I valori mostrati sono stati troncati per facilitarne la lettura.

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

È possibile configurare altri provider di configurazione protetta aggiungendoli al file machine.config. È inoltre possibile creare un proprio provider di configurazione protetta ereditando dalla classe base astratta ProtectedConfigurationProvider. La tabella seguente descrive i due file di configurazione inclusi in .NET Framework.

Provider Descrizione
RsaProtectedConfigurationProvider Usa l'algoritmo di crittografia RSA per crittografare e decrittografare i dati. L'algoritmo RSA può essere usato per la crittografia a chiave pubblica e per le firme digitali. È anche noto come crittografia a "chiave pubblica" o asimmetrica perché impiega due chiavi diverse. È possibile usare lo strumento di registrazione di IIS per ASP.NET (Aspnet_regiis.exe) per crittografare le sezioni di un file Web.config e gestire le chiavi di crittografia. In ASP.NET il file di configurazione viene decrittografato al momento dell'elaborazione. L'identità dell'applicazione ASP.NET deve disporre di accesso in lettura alla chiave di crittografia usata per crittografare e decrittografare le sezioni crittografate.
DpapiProtectedConfigurationProvider Usa DPAPI (Data Protection API) di Windows per crittografare le sezioni di configurazione. Usa i servizi di crittografia incorporati di Windows e può essere configurato per la protezione specifica del computer o specifica dell'account utente. La protezione specifica del computer risulta utile quando più applicazioni sullo stesso server devono condividere informazioni. La protezione specifica dell'account utente può essere usata con i servizi eseguiti con un'identità utente specifica, ad esempio un ambiente di hosting condiviso. Ogni applicazione viene eseguita con un'identità distinta, limitando l'accesso a risorse quali file e database.

Entrambi i provider offrono una crittografia avanzata per i dati. Se tuttavia si prevede di usare lo stesso file di configurazione crittografato in più server, ad esempio una Web farm, solo RsaProtectedConfigurationProvider consente di esportare le chiavi di crittografia usate per crittografare i dati e importarle in un altro server. Per altre informazioni, vedere Importazione ed esportazione di contenitori di chiavi RSA della configurazione protetta.

Utilizzo delle classi di configurazione

Lo spazio dei nomi System.Configuration fornisce classi per specificare le impostazioni di configurazione a livello di codice. La classe ConfigurationManager fornisce accesso a file di configurazione del computer, dell'applicazione e dell'utente. Se si crea un'applicazione ASP.NET, è possibile usare la classe WebConfigurationManager, che fornisce la stessa funzionalità consentendo anche di accedere a impostazioni che sono univoche per le applicazioni ASP.NET, ad esempio quelle disponibili in <system.web>.

Nota

Lo spazio dei nomi System.Security.Cryptography contiene classi che forniscono opzioni aggiuntive per la crittografia e la decrittografia dei dati. Usare queste classi se si richiedono servizi di crittografia che non sono disponibili tramite configurazione protetta. In alcuni casi si tratta di wrapper presenti nelle CryptoAPI di Microsoft non gestite, in altri semplicemente di implementazioni gestite. Per altre informazioni, vedere Servizi di crittografia.

Esempio di App.config

In questo esempio viene illustrato come attivare e disattivare la crittografia della sezione connectionStrings in un file app.config per un'applicazione Windows. La procedura assume il nome dell'applicazione come argomento, ad esempio "MyApplication.exe". Il file app.config verrà quindi crittografato e copiato nella cartella che contiene il file eseguibile con il nome "MyApplication.exe.config".

Nota

La stringa di connessione può essere decrittografata solo nel computer in cui è stata crittografata.

Nel codice viene usato il metodo OpenExeConfiguration per aprire il file app.config per la modifica, mentre il metodo GetSection restituisce la sezione connectionStrings. Viene quindi controllata la proprietà IsProtected, con una chiamata a ProtectSection per crittografare la sezione, se non è crittografata. Il metodo UnprotectSection viene richiamato per decrittografare la sezione. Il metodo Save completa l'operazione e salva le modifiche.

Nota

È necessario impostare un riferimento a System.Configuration.dll nel progetto affinché il codice venga eseguito.

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

Esempio di Web.config

In questo esempio viene usato il metodo OpenWebConfiguration di WebConfigurationManager. Si noti che in questo caso è possibile specificare il percorso relativo del file Web.config usando una tilde. Il codice richiede un riferimento alla classe 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

Per altre informazioni sulla protezione di applicazioni ASP.NET, vedere Securing ASP.NET web sites (Protezione di siti Web ASP.NET).

Vedi anche