les chaînes de connexion
Par amethyste le Jul 18, 2009 | Dans focus | Réagir »
Un article sans autre prétention que rassembler un certain nombre d’informations en général assez éparses sur les chaînes de connexion.
Il n’y a pas d’ordre particulier, juste des chapitres qui se suivent.
un peu d'orthographe
• En anglais on écrit : connection
• Par contre en français : connexion, avec un x.
Allez donc relire votre doc et vos commentaires…
Sauver une chaîne dans une application .net
Examinons différents conteneurs, sans prétendre être exhaustif.
Le code
Cette possibilité est assez rare car dans la majorité des cas il s’agit plutôt d’une faute de codage. Avant de l’adopter, évaluez en les avantages et les inconvénients avec soin.
Le fichier de configuration
Depuis .NET 2.0 est apparue la structure <connectionStrings>.
Par exemple :
<connectionStrings> <add name="nomChaineConnexion" connectionString="XXXXXXXX"/> </connectionStrings>
name: Nom du conteneur
connectionString: Chaîne de connexion
Côté code, la récupération de la chaîne se fait ainsi :
ConnectionStringSettings chaine = ConfigurationManager.ConnectionStrings["nomChaineConnexion"];
Le nom du conteneur peut faire l’objet d’une entrée dans la section <appSettings > que l’on peut alors relire en interrogeant le dictionnaire ConfigurationManager.AppSettings.
La classe ConnectionStringSettings propose diverses propriétés, mais celle qui vous intéressera le plus est ConnectionString qui est du type String et retourne biens sûr notre chaîne.
Qu'en est t'il côté sécurité?
Par défaut ASP.NET est configuré pour ne jamais télécharger le fichier web.config. On n’a donc pas de risque de le voir apparaître en navigant sur le site.
Le réglage est fait dans le fichier web.config par défaut situé dans :
%SystemRoot%\ Microsoft.NET\Framework\v2.0.50727\CONFIG
Ce fichier est apparu avec .NET 2.0, le paramétrage se trouve dans machine.config dans les versions antérieures de .NET.
Ce dernier fichier se trouvant hors répertoire virtuel, il est donc considéré comme raisonnablement sûr pour une application Web, d’autant plus que des ACL sont posées sur ce fichier lors de l’installation de .NET.
La protection contre les attaques extérieures est donc sûre.
On peut encore augmenter la sécurité en cryptant la chaîne de connexion à l’aide de l’outil aspnet_regiis.exe livré avec ASP.NET.
Faisons ensemble une petite démonstration, mais sinon reportez vous à la référence [6] pour plus de détails.
Par exemple (mais d’autres syntaxes existent):
aspnet_regiis -pef "connectionStrings" "C:\Projets\...."
Notez que l’un des paramètres est la section que l’on souhaite crypter, on n’est donc pas limité aux chaînes de connexion.
Le résultat ressemble à ceci :
<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>BkzayktAAs….BDkjEuG3ZVRs/M=</CipherValue> </CipherData> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>UFds9Ssuc6+gHRwt3G…bWqQS31ha</CipherValue> </CipherData> </EncryptedData> </connectionStrings>
Notez plusieurs choses importantes :
• C’est transparent pour votre code
• L’opération est réversible
• Le résultat du cryptage est, par défaut, spécifique à la machine sur lequel il a été effectué, mais il est possible de mettre en place un conteneur RSA particulier comme expliqué en [7]
A ma connaissance cet outil ne s’applique qu’au fichier web .config, du moins je ne suis pas parvenu à l’appliquer à un fichier de configuration d’une application console. Si quelqu’un sait faire sans avoir à renommer le fichier…
Fichier udl (universal data link)
Pour créer un fichier udl :
• Naviguez jusqu’au répertoire où vous souhaitez le déposer
• Créez un fichier texte avec l’extension .udl
• Double cliquez dessus. Une fenêtre suivante s’ouvre
• Remplissez la boite de dialogue.
Une fois terminé, le fichier contiendra la chaîne de connexion complète.
Au sujet du choix du fournisseur, notez que seul OLE DB est supporté par ADO.NET avec les fichiers udl. Mais c’est un moyen que j’aime bien utiliser pour construire une chaîne de connexion.
Côté code maintenant. Disons que votre fichier se nomme monFichierAMoi.udl.
OleDbConnection myConnection = new OleDbConnection("File Name = c:\\monFichierAMoi.udl");
Vous trouverez plus d’infos en [1] et [2].
Côté sécurité?
Ne surtout pas placer le fichier udl dans le répertoire virtuel car il ne sera pas protégé du téléchargement. Pour éviter de possibles bugs de canonicalisation [3], [4], il est même préférable de le disposer dans un volume logique différent de celui du site.
Comme tout fichier critique, il doit être protégé par des ACL adaptés. A ce titre l’accès au fichier udl peut être mieux protégé que celui de web.config car on peut le rendre accessible à nettement moins de comptes. Il y aura au moins MachineName\ASPNET qui n’a besoin que d’un accès en lecture.
Dans la mesure où le fichier udl peut être modifié à l’insu de l’application, celui-ci n’est pas mis en cache, mais lu à chaque appel. Cela peut avoir un impact sur les performances
Il n’est pas possible d’encrypter les fichiers udl.
Fichier personnalisé
Cette option n’est intéressante que si le fichier est placé en dehors du répertoire virtuel pour des raisons de sécurité.
Il doit être protégé par des ACL restrictives et idéalement placé dans un volume distinct de l’application.
Le registre
Pour que l’application ASP puisse y accéder, vous devrez placer la chaîne de connexion dans HKLM. Vous devrez également :
• Protéger la clef avec un ACL
• L’encrypter (voir [5] pour une procédure)
Créer un DSN
Un DSN (Data Source Name) est simplement un fichier avec toutes les informations pour identifier une source de données accessible via ODBC.
Il existe deux types de DSN :
1. Les DSN utilisateur qui ne sont visible que d’un utilisateur sur la machine où le DSN est déployé
2. Les DSN système qui sont accessibles à tous les utilisateurs d’un même système ou connectés au système
Comment faire ?
Il faut rechercher dans le panneau de contrôle le lien vers un utilitaire appelé « ODBC Manager » ou bien « Source de données ODBC ». On le lance et on obtient une fenêtre avec différents onglets. On sélectionne "Source de données système".
Vous trouverez en [14] un tutoriel très bien fait qui vous expliquera la suite.
Côté code rien de très compliqué, vous ouvrez une connexion avec OdbcConnection et créez une chaîne de connexion indiquant juste le nom du DSN avec le mot clef DSN.
Utiliser une chaîne fournie par l'utilisateur
Il peut arriver que la chaîne doive être construite dynamiquement ou bien construite à partir d’informations saisies par l’utilisateur. Dans ce dernier cas, c’est une assez mauvaise idée de le laisser saisir la chaîne elle-même.
Il est plutôt recommandé d’utiliser une des implémentations de la classe DBConnectionStringBuilder pour construire de façon sécurisée une chaîne de connexion. Par exemple pour un fournisseur SQL Server:
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); builder.IntegratedSecurity = false; string maChaine = builder.ConnectionString;
En standard on dispose des implémentations suivantes:
1. SqlConnexionStringBuilder
2. OracleConnexionStringBuilder
3. OdbcConnexionStringBuilder
4. OleDbConnexionStringBuilder
La classe de base DBConnexionStringBuilder vous permettra de fournir votre implémentation pour d’autres cas.
Cette classe est également intéressante si vous souhaitez analyser le contenu d’une chaîne de connexion.
Comment construire une chaîne de connexion
On a déjà vu trois procédés :
1. L’écrire directement à la main
2. Construire un fichier udl et y lire la chaîne résultante
3. Utiliser une classe dérivée de DBConnexionStringBuilder
On peut aussi trouver des exemples de chaînes de connexion toutes faites ici :
http://www.connectionstrings.com
Mais aussi ici :
http://connectionstringexamples.com
Vous y trouverez des centaines d’exemples de chaînes de connexion pour de nombreuses bases de données.
Retenez au moins ceci :
• Les noms ne sont pas sensibles à la casse (mais les valeurs éventuellement, exemple les mots de passe)
• Les valeurs ne sont pas typées
• Si une même paire nom=valeur apparaît plusieurs fois, seule la dernière sera prise en compte
• Mais : si le mot clef PROVIDER apparaît plusieurs fois, c’est le premier qui est pris en compte !!!!
• Les valeurs true ou false peuvent aussi s’écrire yes ou no
Vous trouverez plus d’informations ici :
http://www.connectionstrings.com/Articles/Show/important-rules-for-connection-strings
On trouve quoi dans une chaîne de connexion
A ma connaissance il n’existe pas de norme particulière, chaque conteneur de données y place ce qu’il souhaite. Mais on retrouve malgré tout une certaine systématique.
L’article qui suit liste la plupart des paramètres que l’on peut rencontrer dans une chaîne de connexion avec leurs valeurs par défaut :
http://www.connectionstrings.com/Articles/Show/all-sql-server-connection-string-keywords
Comme vous le constatez, il y a beaucoup de synonyme.
INITIAL CATOLOG
On rencontre aussi DATABASE. Désigne la base de données associée à la connexion.
DATA SOURCE
Ou aussi SERVER et plein d’autres d’ailleurs !
Nom ou adresse réseau de l’instance de la base de données à laquelle se connecter.
Ce que j’ai appris récemment est que l’on peut y passer le nom du protocole de communication utilisé :
DATASOURCE=np :
Pour les canaux nommés (named pipe).
Mais aussi un numéro de port si celui par défaut ne convient pas :
DATASOURCE=tcp :
PERSIST SECURITY INFO
Ce paramètre prend true ou false. La valeur par défaut est false.
D’après la documentation cette valeur indique que les informations de sécurité telles le mot de passe, sont retournées dans le cadre de la connexion si celle-ci est ouverte ou a été ouverte à un moment donné.
Personnellement ce genre de définition ne me semble pas bien claire. Je ne vois pas bien ce que cela impacte pour moi et encore moins dans quels cas je dois choisir une valeur plutôt qu’une autre.
Comme souvent, un petit essai clarifie les choses :
using (SqlConnection connnexion = new SqlConnection("Persist Security Info=false;Data Source=.;Initial Catalog=Northwind;Uid=IsgUser;Pwd=ISGuser!")) { string avant = connnexion.ConnectionString; connnexion.Open(); string apres = connnexion.ConnectionString; using (SqlCommand commande = connnexion.CreateCommand()) { commande.CommandText = "select * from Customers"; using (SqlDataReader reader = commande.ExecuteReader(CommandBehavior.CloseConnection)) { int ordinal = reader.GetOrdinal("CompanyName"); while (reader.Read()) { Console.WriteLine(reader.GetString(ordinal)); } } } }
Le code interroge la base NorthWind et lit le contenu d’une table. Notez la valeur explicitement mise à false du paramètre PERSIST SECURITY INFO dans la chaîne de connexion.
Nous ne nous intéressons qu’aux deux variables avant et apres que l’on visualise ainsi :

Effectivement ce n’est pas bien difficile de comprendre PERSIST SECURITY INFO.
La chaîne de connexion complète, avec les credentials, est nécessaire pour créer le pool de connexion et se connecter à la source de données (ce que fait la méthode Open).
Par contre une fois la connexion établie, les parties sensibles du credential sont supprimées. Il devient possible de passer la connexion à une application qui n’est pas une application de confiance puisqu’elle ne pourra pas réutiliser la valeur de la propriété ConnectionString pour récupérer vos credentials.
La conclusion de tout cela est que l’on n’a que rarement l’occasion de mettre true et si vous souhaitez loguer la chaîne de connexion, mieux vaut donc apres que avant.
INTEGRATED SECURITY
Egalement appelée « trusted connection ».
Voici les valeurs possibles de cette propriété :
• SSPI (Security Support Provided Interface)
• true
• false qui est aussi la valeur par défaut
True indique que l’on se connecte avec les credentials fournis par le compte Windows courant.
False indique que la chaîne de connexion doit fournir des credentials (paramètres USER ID et PWD).
Et SSPI me direz vous ?
J’ai longtemps cru que cette valeur était synonyme de true, mais en fait ce n’est pas toujours le cas comme je l’ai découvert en lisant un article du blog « La voie du code« [9].
SSPI est une API Microsoft destinée à effectuer un certain nombre d’opérations liées à la sécurité comme par exemple l’authentification [10]. SSPI permet donc de disposer d’une interface commune pour accéder à des protocoles tels Kerberos ou NTLM.
Par conséquent l’option SSPI ne fonctionnera que si votre protocole réseau utilise SSPI.
Parmi les exceptions se trouvent justement les canaux nommés (named pipes). Dans ce cas il faut donner true comme valeur d’INTEGRATED SECURITY.
Si vous êtes amenés à vous servir des canaux nommés dans une application ASP.NET lisez l’article en [11].
Si vous souhaitez en savoir plus sur les protocoles réseaux accessibles à SQL lisez [12] et [13].
SqlBulkCopy
Cette classe apparue avec .NET 2.0 permet de charger en bloc une table SQL Server avec des données provenant d’une autre source, pas nécessairement SQL Server. Il suffit de pouvoir les lire dans un DataSet ou bien avec une instance d’IDataReader.
Cette classe fonctionne un peu comme l’utilitaire en ligne bcp fournit avec SQL Server.
Les performances sont bien meilleures qu’avec des INSERT, mais on perd les logs.
Spécial sql express
SQL Express a diverses particularités et notamment la notion d’interface utilisateur (user instance) utilisée par les projets se servant de base de données locale. User instance est un process spécifique à SQL Express qui peut être démarré par votre application au cours de son exécution. Du point de vue du code, tout se passe comme si vous disposiez d’une base de données embarquée.
Voici deux articles qui vous diront tout à ce sujet :
http://msdn.microsoft.com/fr-fr/library/bb264564(SQL.90).aspx
Et en anglais un blog vraiment intéressant où vous apprendrez à vous connecter à une user instance via management studio:
http://blogs.msdn.com/sqlexpress/archive/2006/11/22/connecting-to-sql-express-user-instances-in-management-studio.aspx
Bibliographie
[1] Comment faire pour utiliser des fichiers de liaison de données avec l'objet OleDbConnection dans Visual C# .NET
http://support.microsoft.com/kb/308426
[2] ADO.NET and UDL
http://www.codeproject.com/KB/database/ADONETUDL.aspx[3] Les attaques par canonicalisation 1/2
http://www.dotnetguru2.org/amethyste/index.php?p=103&more=1&c=1&tb=1&pb=1
[4] Les attaques par canonicalisation 2/2
http://www.dotnetguru2.org/amethyste/index.php?p=104&more=1&c=1&tb=1&pb=1
[5] Procédure : Stocker une chaîne de connexion cryptée dans le Registre
http://msdn.microsoft.com/fr-fr/library/aa302406.aspx
[6] Outil ASP.NET IIS Registration (Aspnet_regiis.exe)
http://msdn.microsoft.com/fr-fr/library/k6h9cz8h(VS.80).aspx
[7] Crypter une section du fichier de configuration avec aspnet_regiis
http://blogs.developpeur.org/sanzio/archive/2008/04/14/crypter-une-section-du-fichier-de-configuration-avec-aspnet-regiis.aspx
[8] Secure ADO.NET connections
http://msdn.microsoft.com/en-us/library/89211k9b(VS.71).aspx
[9] Le vrai sens de Integrated Security=SSPI
http://www.doanvanbien.com/voieducode/archives/2006/09/13/21
[10] SSPI Reference sur MSDN
http://msdn.microsoft.com/en-us/library/aa380493(VS.85).aspx
[11] Les canaux nommés ne fonctionnent pas quand le processus de traitement s'exécute sous un compte ASPNET
http://support.microsoft.com/Default.aspx?id=315159
[12] [SQL] Force the protocol (TCP, Named Pipes, etc.) in your connection string
http://weblogs.asp.net/jgalloway/archive/2007/02/24/sql-force-the-protocol-tcp-named-pipes-etc-in-your-connection-string.aspx
[13] Choix d’un protocol réseau
http://msdn.microsoft.com/fr-fr/library/ms187892.aspx
[14] Création d’un DSN ODBC
http://www.commentcamarche.net/contents/odbc/odbcdsn.php3
Commentaires en attente de modération
Cet article a 1 réaction en attente de modération...
Laisser un commentaire
| « WPF : Débogage des bindings [ajout] | Accélérer MSDN » |