Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Criptare le stringhe di connessione

Realizzare una utility per criptare e decriptare sezioni del file di configurazione
Realizzare una utility per criptare e decriptare sezioni del file di configurazione
Link copiato negli appunti

In ASP.NET abbiamo due possibilità di trattare le stringhe di connessione. Una è quella di scriverle direttamente nelle pagine dell'applicazione o nel codice interno delle stesse, l'altra è di salvarle all'interno del file di configurazione, il "Web.Config".

La seconda scelta è la più indicata perchè facilità le operazioni di manutenzione ed aumenta le leggibilità del codice.

Le stringhe di connessione in genere contengono informazioni che è bene celare ad occhi indiscreti. Un malintenzionato che ne venisse a conoscenza potrebbe usarle per accedere al database dell'applicazione.

Con ASP.net 2.0 possiamo criptare le stringhe di connessione in fase di programmazione. Questo significa che lo sviluppatore può usare delle classi già pronte per criptare delle parti di codice.

La situazione auspicata è quella di avere a disposizione delle utility in locale, per trasformare le parti di codice più sensibili, in modo da portare online solo codice sicuro, cioè non leggibile e quindi non riproducibile.

Per realizzare l'esempio di questo articolo usiamo il database di esempio PUBS, che si può scaricare dal sito della Microsoft, il VWD (Visual Web Developer) ed il linguaggio C#.

Supponiamo di aver scaricato il nostro database di esempio nella cartella "SQL Server 2000 Sample Databases" sul disco C, come in figura.

Figura 1. Database di esempio PUBS
Database di esempio PUBS

Con il VWD apriamo un "New Web Site" e lo chiamiamo "CriptareStringheConnessione" come in figura, in cui abbiamo scelto una localizzazione sul nostro file system ed il linguaggio C#.

Figura 2. Nuovo sito CriptareStringheConnessione

New Web Site CriptareStringheConnessione

In Design view della "Default.aspx", trasciniamo un GridView. Configuriamo il GridView affinchè usi un SqlDataSource che attinga dal file di database "PUBS.MDF". Possiamo scegliere di visualizzare la tabella "authors" o un'altra tabella, tale scelta non è importante per i nostri scopi.

La situazione che ci si presenta è questa:

Figura 3. Visualizzazione di una tabella del database PUBS
Visualizzazione di una tabella del database PUBS

La cosa importante è il file di configurazione che è stato automaticamente creato dal VWD e che riportiamo nel listato 1, mettendo in evidenza la sezione "connectionStrings".

Listato 1. Web.Config

<?xml version="1.0"?>
<configuration>
<appSettings/>

<connectionStrings>
 <add name="PUBSConnectionString"
  connectionString="Data Source=.SQLEXPRESS;
    AttachDbFilename="C:SQL Server 2000 Sample DatabasesPUBS.MDF";
    Integrated Security=True;
    Connect Timeout=30;
    User Instance=True"
  providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
<compilation debug="false" />
<authentication mode="Windows" />
</system.web>
</configuration>

Realizziamo quindi la nostra utility per criptare le stringhe di connessione. Aggiungiamo un nuovo Item di nome "Utility.aspx" e scegliamo di separare il codice interno.

Andiamo nel codice interno della Utility.aspx, contenuto nella Utility.aspx.cs, ed implementiamo i metodi che ci consentono di criptare e decriptare la stringa di connessione del Web.Config.

Cominciamo con il metodo Cripta() riportato e commentato nel listato 2.

Listato 2. Metodo Cripta()

public void Cripta(string protectionProvider)
{
  // apriamo il file di configurazione
  Configuration WebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
  // specifichiamo la sezione da criptare
  ConfigurationSection sezioneProt = WebConfig.Sections["connectionStrings"];
  // specifichiamo il protection provider da applicare alla sezione da criptare
  sezioneProt.SectionInformation.ProtectSection(protectionProvider);
  // salviamo il file di configurazione modificato
  WebConfig.Save();
}

Nel metodo Cripta(), preleviamo il file di configurazione utilizzando il percorso dell'applicazione. Questo non genera ambiguità poichè in una cartella ci può essere un solo file di configurazione. Specifichiamo poi che vogliamo criptare le stringhe di connessione ed il Provider da utilizzare. Infine salviamo il Web.Config criptato.

Ci sono due possibili provider di protezione:

  • il DataProtectionConfigurationProvider che usa DPAPI di Windows
  • l'RSAProtectedConfigurationProvider che usa l'algoritmo public-key disponibile nella classe RSACryptoServiceProvider del Framework .NET .

Implementiamo ora il metodo DeCripta() che riportiamo nel listato 3.

Listato 3. Metodo DeCripta()

public void DeCripta()
{
  // apriamo il file di configurazione
  Configuration WebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
  // specifichiamo la sezione criptata
  ConfigurationSection sezioneProt = WebConfig.Sections["connectionStrings"];
  // decriptiamo la sezione criptata
  sezioneProt.SectionInformation.UnprotectSection();
  // salviamo il file di configurazione modificato
  WebConfig.Save();
}

Al metodo DeCripta() non dobbiamo dire quale provider di protezione abbiamo usato in fase di criptazione, in quanto questa informazione è salvata direttamente sul file di configurazione.

Passiamo ora alla Utility.aspx ed implementiamo un RadioButtonList come in figura 4.

Figura 4. RadioButtonList di utility
RadioButtonList di utility

Clicchiamo due volte sul RadioButtonList ed implementiamo il gestore dell'evento OnSelectedIndexChanged nella parte di codice interno, come nel listato 4.

Listato 4. Gestore dell'evento OnSelectedIndexChanged

protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
  switch (RadioButtonList1.SelectedIndex)
  {
    case 0:
      Cripta("DataProtectionConfigurationProvider");
      Messaggio1.Text = "Web.Config criptato con il DataProtection";
    break;
    case 1:
      Cripta("RSAProtectedConfigurationProvider");
      Messaggio1.Text = "Web.Config criptato con l'RSA";
    break;
    case 2:
      DeCripta();
      Messaggio1.Text = "Web.Config decriptato";
    break;
  }
}

RadioButtonList1_SelectedIndexChanged non fa altro che fornire al metodo Cripta il provider di protezione scelto dallo sviluppatore con il RadioButtonList presente nell'utility di criptazione oppure chiamare il metodo DeCripta. Al fine di capire meglio che cosa sta succedendo, abbiamo messo una Label di informazione, come dovrebbe fare ogni buon programmatore.

Possiamo ora testare la nostra utility. Selezioniamola e premiamo F5. Selezioniamo "Cripta con DataProtectionConfigurationProvider" e se abbiamo configurato il RadioButtonList per l'AutoPostBack, otteniamo subito il risultato mostrato il figura 5, in cui un messaggio ci informa di ciò che è successo.

Figura 5. Criptiamo con la nostra utility
Criptiamo con la nostra utility

Chiudiamo la nostra applicazione e torniamo al VWD, questo ci chiede se vogliamo ricaricare il Web.Config che è stato modificato all'esterno del suo editor. Diciamogli di si per poter vedere le modifiche. Il file "Web.Config" modificato risulta essere come nel listato 5.

Listato 5. Web.Config con stringa di connessione crifrata

<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
  <CipherData>
  <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sB ... TEUAAAA4YX9e03M+X56k+VUlWepDgrRnDw=
  </CipherValue>
  </CipherData>
  </EncryptedData>
</connectionStrings>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
</system.web>
</configuration>

Nel listato 5, dove per semplicità abbiamo omesso gran parte dei valori cifrati, possiamo notare l'informazione riguardo al provider di protezione che è stato usato. Non è presente inoltre la chiave di protezione che, nel caso del provider scelto nell'esempio, viene salvata nella Local Security Autority (LSA) di Windows.

A questo punto possiamo testare l'applicazione con il nuovo Web.Config e verificare che funzioni. Possiamo inoltre testare il decriptaggio e l'altro metodo di criptaggio.

Si possono proteggere quasi tutte le sezioni del Web.Config. Per verificare se una sezione è protetta, si può usare la proprietà IsProtected della classe SectionInformation. Possiamo ad esempio modificare il nostro codice in modo che operi il criptaggio solo se non è stato già operato e fare un discorso analogo per il decriptaggio.

Listato 6. Metodo Cripta() con il controllo sulla protezione già operata

public void Cripta(string protectionProvider)
{
  // apriamo il file di configurazione
  Configuration WebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
  // specifichiamo la sezione da criptare
  ConfigurationSection sezioneProt = WebConfig.Sections["connectionStrings"];
  //verifichiamo di non aver già codificato
  if (!sezioneProt.SectionInformation.IsProtected)
  {
    // specifichiamo il protection provider da applicare alla sezione da criptare
    sezioneProt.SectionInformation.ProtectSection(protectionProvider);
    // salviamo il file di configurazione modificato
    WebConfig.Save();
    Messaggio1.Text = "Web.Config criptato con " + protectionProvider;
  }
  else
   Messaggio1.Text = "Web.Config già criptato";
}

Se abbiamo un Web.Config in cui le stringhe di connessione sono crifrate, come è il caso del listato 4, e cerchiamo di aggiungere una nuova stringa di connessione in fase di programmazione, essa verrà automaticamente cifrata, come possiamo verificare utilizzando ad esempio il metodo aggiungiStringaConnessione() riportato nel listato 7.

Listato 7. Metodo aggiungiStringaConnessione()

public void aggiungiStringaConnessione()
{
  Configuration WebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
  ConnectionStringSettings connStrSettings = new ConnectionStringSettings("NORTHWNDConnectionString", "Data Source=.\SQLEXPRESS;AttachDbFilename="C:\SQL Server 2000 Sample Databases\NORTHWND.MDF";Integrated Security=True;Connect Timeout=30;User Instance=True");
  WebConfig.ConnectionStrings.ConnectionStrings.Add(connStrSettings);
  WebConfig.Save();
}

Il codice sorgente dell'esempio sviluppato in questo articolo può essere scaricato da qui.

Ti consigliamo anche