[.NET] Crypter la section « connectionStrings » du fichier app.config (ou web.config)

Le 2 février 2010 à 19:23

Pour rappel, la section « connectionStrings » du fichier App.config contient les informations d’accès à vos bases de données comme le chemin d’accès, le login et le mot de passe. Ces informations sont donc sensibles et ne doivent pas être dévoilés aussi facilement.
Malgré qu’il soit évident qu’il ne faut pas utiliser un compte « root » de la base de données, il est tout de même plus prudent de cacher cette partie aux yeux des utilisateurs. D’autant plus qu’avec cette méthode, l’utilisateur final ne pourra pas modifier le fichier manuellement.

Voici le fichier App.config et la section “connectionStrings” sous sa forme habituelle :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="SqlCustomersDB" 
         providerName="System.Data.SqlClient" 
         connectionString="Data Source=MPE-SERV\SQLSERVER_ITESTS;
                           Initial Catalog=CustomersDB;
                           User ID=perrein;
                           Password=P@ssw0rD" />
  </connectionStrings>
</configuration>

Et voici le même fichier App.config et la section “connectionStrings” que l’on va avoir sous sa forme “protégé” :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>HvU+CmZBPbPfqGvhBLE8OC2QmO3V7w0gwpTr7CBkMifC15H8eQ8Z
                         AmyxCQRpP/Tz8gypkQ1PDyQdyYD26sa/I1PaJzrZpduypLD2mp9p
                         kyWXAygFRQvb0m4EL0OK8DoHDWMta1q7Q7BycVOU87ePeCQ8Z7MY
                         XGoySopx7nzvBeI=
            </CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>vo42yCFwoVO3s4Md+Jcl9rLHQCRcVDTXr9JGFxjN4ozlGdG9TFrI16+J
                     y1CTWzgi1bXwYtFCfSUgRjMJbYm6ULLGFcFaaX7h/1O+9tfUtrLjbBuJ
                     4wO6q0xr766lrOpQ98BG9rqxm6WwEVWZfT/FesDkzWVw/N+W8FPPk1rg
                     +QTSB7ZisjqhGSkoZERgVe2MsCtl5ZJyQawFvy0DreWdj7efNT2aMs1N
                     Ieogmef0/XTB4nXYjEA8I7R9AnjekWwDnXHAcpFzYjoqgmFx8zHG+XPQ
                     xeXVhCue5QmshNDzuRg=
        </CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
</configuration>

Pour transformer le fichier, la mise en place n’est pas très compliquée, il faut utiliser la méthode SectionInformation. ProtectSection de la classe ConfigurationSection :

Configuration config = 
              ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection section = config.GetSection("connectionStrings");

if (section != null)
{
    if (!section.IsReadOnly() && !section.SectionInformation.IsProtected)
    {
        section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
        section.SectionInformation.ForceSave = true;
        config.Save(ConfigurationSaveMode.Full);
    }
}


On peut crypter cette section avec deux providers :
- DataProtectionConfigurationProvider : utilise l’API de protection des données (DPAPI) Windows pour chiffrer et déchiffrer
- RsaProtectedConfigurationProvider : utilise le chiffrement RSA pour chiffrer et déchiffrer les données de configuration

Pour lire une connectionStrings dans le fichier de configuration, rien ne changera par rapport à nos habitudes car le décryptage est totalement transparent. Par contre, s’il faut modifier ou supprimer une valeur, il faudra décrypter la section au préalable : 

Configuration config = 
              ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection section = config.GetSection("connectionStrings");

if (section != null)
{
    if (section.SectionInformation.IsProtected)
    {
        section.SectionInformation.UnprotectSection();
        section.SectionInformation.ForceSave = true;
        config.Save(ConfigurationSaveMode.Full);
    }
}
config.ConnectionStrings.ConnectionStrings["SqlCustomersDB"].ConnectionString = 
   @"Data Source=MPE-SERVER-02\SQLSERVER;Initial Catalog=CustomersDB;
                 Integrated Security=True;User ID=perrein;Password=P@ssw0rD";
config.Save();

// Modification du fichier de configuration
// ...
// On crypte à nouveau le fichier de configuration une fois les modifications 
// terminées et enregistrées

A bientôt :-).

Visual Studio 2010 Beta 2

Le 21 octobre 2009 à 09:04

Une petite nouvelle qui pourrait en intéresser plus d’un :).
Le téléchargement “tout public” est disponible sur le site de Microsoft (lien).


Bon téléchargement !

WPF : traduisez vos applications en plusieurs langues avec LocBaml

Le 26 septembre 2009 à 18:30

Avec WPF, pour localiser une application, il faut passer par un outil externe : LocBaml (à télécharger ici). Cet outil, en ligne de commande, se révèle très simple d’utilisation. Sa fonction est de nous permettre d’extraire les ressources nécessaires à la traduction et de générer des assemblys satellites en plusieurs langues.

Pour cela, il va falloir procéder en plusieurs étapes.

1) Indiquer la langue par défaut du projet

Pour cela, il faut dans le fichier .csproj, définir une balise supplémentaire : UICulture. Avec cette balise, et après régénération du projet, il va nous créer l’assembly satellite par défaut.

Note : liste des cultures possibles (NLS) : http://www.microsoft.com/resources/msdn/goglobal/default.mspx

image_3

Ci-dessous, on peut remarquer qu’un nouveau dossier a été crée qui contient la ressource de la langue.

image_4

Jusque là, rien de bien compliqué (comme ce qui va suivre d’ailleurs), maintenant on va s’intéressé à l’outil LocBaml.

2) Extraire les ressources pour la traduction

Prenons le code XAML suivant :

<Grid>
    <Button x:Name="ButtonHello" Height="100" Width="100">Bouton (FR)</Button>
</Grid>

Dans l’état des choses, LocBaml ne peut pas extraire les ressource parce qu’il n’y a aucun ID au bouton (Name ne suffit pas). Pour cela, il faut implémenter la balise x:Uid. Pour cela, nous avons deux choix : l’implémenter manuellement, ou bien utiliser MSBuild. Par “sécurité”, je préfère MSBuild, ça me permet de ne rien oublié.

Utilisation de la commande MSbuild :

msbuild /t:updateuid LocBamlSample.csproj

A présent le projet est à jour avec les Uid.
Note : nous pouvons faire aussi un check avant de mettre à jour les Uid :

msbuild /t:checkuid LocBamlSample.csproj

Maintenant, voici le code XAML modifié avec les x:Uid, nous constatons qu’il a ajouté un Uid à Grid et à ButtonHello :

<Grid x:Uid="Grid_1">
    <Button x:Uid="ButtonHello" x:Name="ButtonHello" Height="100" Width="100">
        Bouton (FR)
    </Button>
</Grid>

Une fois cette étape de franchi, il nous reste qu’à utiliser LocBaml afin d’extraire les ressources (les Uid avec leur contenu) afin de les traduire dans une langue différente.

Pour cela, nous utilisons la commande suivante (note : nous pouvons exporter aussi en CVS, comme il le fait par défaut, mais avec Excel, nous pouvons avoir quelques soucis de double quote) :

LocBaml /parse LocBamlSample.exe /out:en.txt

Voici le fichier généré par l’outil :

image_5


A présent, nous avons notre fichier de ressource prêt à l’emploi pour une traduction. Pour notre exemple, je vais modifier le Content du bouton en “Button (EN)”.

Maintenant, on va générer notre assembly satellite qui nous permettra d’avoir notre application disponible en français et en anglais. Pour cela, il faut créer un dossier “en-US” qui accueillera la ressource en anglais dans le répertoire de l’application (ici Debug). Maintenant on va générer l’assembly, toujours avec LocBaml :

locbaml /generate fr-Fr\LocBamlSample.resources.dll /trans:en.txt /out:en-US /cul:en-US

Voilà, notre assembly satellite est crée et prêt à l’emploi.


3) Changer la langue de l’application

En principe, l’application change de langue selon la culture de l’utilisateur, mais voici la procédure à suivre pour changer de langue de l’application par code.
Dans le fichier App.cs, il suffit de changer la culture du thread en cours :

public partial class App : Application
{
    public App()
    {
        CultureInfo culture = new CultureInfo("en-US");
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
}

Voici le résultat à l’exécution :
image_6

 

Il a bien changé la langue de l’application.

Maintenant la question qui peut se poser, c’est comment faire pour les chaîne de caractères utiliser dans son code C# ?

4) Dictionnaire de ressources

Pour cela, il faut créer un dictionnaire de ressources dans le projet, qui nous permettra ensuite d’extraire les ressources (bien entendu, il faut ré-exécuter l’outil MSBuild et LocBaml pour avoir les modifications dans le fichier de ressource anglais) :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:system="clr-namespace:System;assembly=mscorlib">

    <system:String x:Uid="Bonjour" x:Key="MessageBox">Bonjour tout le monde</system:String>
</ResourceDictionary>

Note : ne pas oublier de l’ajouter dans le fichier App.xaml (voir code source du projet).
J’ajoute en même temps, pour notre exemple, un MessageBox affichant le message “Bonjour tout le monde” au click sur le bouton :

private void ButtonHello_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show((string)Application.Current.Resources["Bonjour"]);
}

Maintenant, il faut à nouveau suivre les procédures évoquées plus haut concernant l’extraction et la génération de l’assembly satellite anglais afin de le mettre à jour.

image_7 

A présent, nous avons une application multilingue. Note : s’il manque une ressource (en-US par exemple), l’application sera exécuter dans la langue par défaut et dans notre cas le français.

A bientôt :)

Télécharger le code source ici.

Entity Framework : générer le modèle pour une base autre que SQL Server

Le 23 septembre 2009 à 16:28

Actuellement je travaille sur un gros projet qui est utilisé avec PostgreSQL. Malheureusement, le provider de cette base de données (Npgsql) ne prends pas en charge une intégration totale avec les possibilités offertes par les interfaces de Visual Studio. Il nous est donc impossible de générer l’Edmx via Visual Studio. Bien sûr, il existe des providers payants qui permettent de le faire (je pense bien sûr à Devart), mais ce n’est pas le but de l’article.

wizard-edm
C’est pour cela qu’il existe un fabuleux outil qui s’appelle “EdmGen2” disponible sur le MSDN Code Gallery. L'outil peut être utilisé comme un remplacement pour l'outil EdmGen qui est fourni avec le Framework. Net 3.5 SP1. EdmGen ne peut que lire et écrire les fichiers CSDL, SSDL et MSL. Par contre, EdmGen2 peut lire et écrire le format de fichier EDMX utilisée par les outils de conception de Visual Studio.

Note : avant de générer le fichier, il faut s’assurer que le provider est installé dans le GAC.

Donc, pour générer le fichier Edmx de notre base PostgreSQL, nous allons utiliser l’option modelgen d’edmgen2.exe, où il faut respecter la syntaxe suivante :

image 

edmgen2.exe /modelgen "Port=5432;Encoding=WIN1252;Server=IBM-SERVER;
                       Database=Northwind;UserId=postgres;Password=1234" Npgsql Northwind

 

Une fois la commande effectuée, vous aurez le fichier Northwind.edmx de crée, il vous suffira de l’ajouter à votre projet et il sera utilisable directement.

edmx

Note : n’oubliez pas votre fichier App.config, il ne sera pas crée automatiquement, comme avec l’assistant de Visual Studio ;-).

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
  </configSections>
  <connectionStrings>
    <add name="NorthwindEntities" connectionString=
        "metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://*/Northwind.msl;
        provider=Npgsql;provider connection string=&quot;
        Port=5432;Encoding=WIN1252;Server=IBM-SERVER;
        Database=Northwind;UserId=postgres;Password=1234&quot;"
      providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

A bientôt :)

Entity Framework : Log ?

Le 22 septembre 2009 à 10:07

Avec Linq To Sql, on a l’habitude, en phase de débogage, d’utiliser le code suivant :

AdventureWorksData context = new AdventureWorksData();
context.Log = Console.Out;

Le log nous permet de voir toutes les requêtes qui sont générées par Linq To Sql. Donc, avec le code suivant, nous aurons en console la requête générée :

AdventureWorksData context = new AdventureWorksData();
context.Log = Console.Out;

var query = from p in context.Product
            where p.Color.Equals("Black")
            select p;

foreach (var q in query)
{
    Console.WriteLine(q.ProductID);
}

Console.Read();

// Requête générée envoyée dans la console
SELECT [t0].[ProductID], [t0].[Name], [t0].[ProductNumber], 
       [t0].[MakeFlag], [t0].[FinishedGoodsFlag], [t0].[Color],
       [t0].[SafetyStockLevel], [t0].[ReorderPoint],
       [t0].[StandardCost], [t0].[ListPrice], [t0].[Size], 
       [t0].[SizeUnitMeasureCode], [t0].[WeightUnitMeasureCode],
       [t0].[Weight], [t0].[DaysToManufacture], [t0].[ProductLine],
       [t0].[Class], [t0].[Style], [t0].[ProductSubcategoryID], 
       [t0].[ProductModelID], [t0].[SellStartDate], [t0].[SellEndDate],
       [t0].[DiscontinuedDate], [t0].[rowguid], [t0].[ModifiedDate]
FROM [Production].[Product] AS [t0]
WHERE [t0].[Color] = @p0

Avec EF, cela ne se met plus en place tout à fait de la même manière. Nous pouvons faire le log avec ObjectQuery.ToTraceString(). Voici l’exemple ci-dessus remodelé pour EF et ToTraceString() :

AdventureWorksEntities context = new AdventureWorksEntities();

var query = from p in context.Product
            where p.Color.Equals("Black")
            select p;

// Affiche la requête
Console.WriteLine(context.Product.ToTraceString());

foreach (var q in query)
{
    Console.WriteLine(q.ProductID);
}

Console.Read();

// Requête générée
SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[Name] AS [Name],
[Extent1].[ProductNumber] AS [ProductNumber],
[Extent1].[MakeFlag] AS [MakeFlag],
[Extent1].[FinishedGoodsFlag] AS [FinishedGoodsFlag],
[Extent1].[Color] AS [Color],
[Extent1].[SafetyStockLevel] AS [SafetyStockLevel],
[Extent1].[ReorderPoint] AS [ReorderPoint],
[Extent1].[StandardCost] AS [StandardCost],
[Extent1].[ListPrice] AS [ListPrice],
[Extent1].[Size] AS [Size],
[Extent1].[SizeUnitMeasureCode] AS [SizeUnitMeasureCode],
[Extent1].[WeightUnitMeasureCode] AS [WeightUnitMeasureCode],
[Extent1].[Weight] AS [Weight],
[Extent1].[DaysToManufacture] AS [DaysToManufacture],
[Extent1].[ProductLine] AS [ProductLine],
[Extent1].[Class] AS [Class],
[Extent1].[Style] AS [Style],
[Extent1].[ProductSubcategoryID] AS [ProductSubcategoryID],
[Extent1].[ProductModelID] AS [ProductModelID],
[Extent1].[SellStartDate] AS [SellStartDate],
[Extent1].[SellEndDate] AS [SellEndDate],
[Extent1].[DiscontinuedDate] AS [DiscontinuedDate],
[Extent1].[rowguid] AS [rowguid],
[Extent1].[ModifiedDate] AS [ModifiedDate]
FROM [Production].[Product] AS [Extent1]

On remarquera qu’à la différence avec Linq to Sql, il faut définir exactement quelle requête nous voulons voir.

Bien sûr, si vous utilisez SQL Server, vous pouvez aussi utiliser SQL Profiler, pour avoir un monitoring plus “poussé”. Pour les autres bases de données, il existe aussi des outils équivalents.

A propos de l'auteur

Mathieu Perrein - Software Solutions Manager, Software Architect, Trainer MCT, MSP de 2010 à 2012.

 

MSP

 

MSP

MSP

 MSPD

MCT

 

Facebook

 

Ce blog est strictement personnel et les opinions exprimées ici n'engagent donc que moi, et pas mon employeur.

Tags

Vous avez désactivé JavaScript ou bien vous possédez une ancienne version d'Adobe Flash Player. Téléchargez la dernière version de Flash Player.