So, how do you manage connection strings in your ASP.NET applications? Since version 2.0 of ASP.NET, the most common answer to this was: By placing them all in the <connectionStrings> section of the root <configuration> node of the web.config.
<connectionStrings>
<configuration>
The next logical question would be: How do you make sure that wrong people can't read those strings? By encrypting them, of course. After all, doesn't Microsoft itself enforce this approach? Didn't all well-established publications make this a de-facto method of connection string management in ASP.NET?
Yes, they did. But let's examine all this one more time, this time from a slightly different angle.
Indeed, we do need a reliable way to protect our connections from preying eyes. And encryption seems to be the only choice here. But let's list the concerns that programmers typically have when they manage encrypted connections in ASP.NET these days:
DevConn_Server_GHYT65TY
StagingConn_Local
Now that we listed our concerns, let's examine what we really want to achieve here.
DevConn
ProdServerConn
Here is what I don't understand: you can achieve all this that I just mentioned above in seconds right now without degrading the security of your application in any way and you were able to do this since the very first public beta of ASP.NET (April of 2000, I believe). And yet, almost no one brings this to your attention. So, what is it?
Let's do this: create a test web application. Make sure there is a web.config file. Add a new XML file to the root folder of the project, name it AppSettings.config (the .config extension will not allow the run time to serve it over HTTP). Add the following content to that new file:
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="DbConnection" value="-- whatever your connection string is --"/>
</appSettings>
Note that you can omit the XML declaration on top of the file - ASP.NET parser will understand it properly anyway.
Now, add the "file" attribute to the <appSettings> node of your web.config file with the value of the file name of that AppSettings.config file:
<appSettings>
<?xml version="1.0"?>
<configuration>
<appSettings file="AppSettings.config">
<add key="SomeTestKey" value="SomeTestValue"/>
</appSettings>
</configuration>
The little dirty secret here is that the "file" attribute tells the parser to load the AppSettings.config file while it reads the web.config. It then "injects" its content to the <appSettings> node. Now you can access the value of that "DbConnection" key from the AppSetttings.config file as you would normally access any other "appSettings" key from the web.config:
DbConnection
appSettings
using System.Configuration;
namespace Test.Web.Application
{
internal class Settings
{
/// <summary>
/// Connection string to the database
/// </summary>
public static string DbConnection
{
get { return ConfigurationManager.AppSettings["DbConnection"]; }
}
}
}
(I assume you're a good professional and rather than accessing configuration values from your pages or forms directly, you have a type that exposes those values as its strongly typed properties.)
I think, it's clear by now that this approach gives us a much better and simpler management of our connections. We can create multiple setting files, one for every server or environment. Those files can contain values specific to their current environments. You create them once, save them on their servers and truly forget about environment-specific settings. Every time you deploy an application to a different environment, you move all application files except for the settings file.
This allows us not to encrypt connections at all. And yet we can reliably control who has access to those connections. Therefore, our first three concerns were just eliminated all at once.
Most developers shouldn't have access to a production environment anyway. With separate setting files in place, developers will never see the production or other "important" connections because they are not the ones who created those files. Programmers can move between projects, leave the company - rest assured that they simply cannot take company's sensitive data with them. So, we eliminated our last concern as well. And we achieved everything that we wanted to achieve.
But wait a second... No one said that everything above applies to DB connections only.
For example, payment gateway credentials for shopping carts. Does the current environment use "sandboxes" or "live" values. What about SMTP credentials? Or server-specific paths? And so on, and so forth. Basically, you can (and should) keep all static environment-independent settings in the web.config itself and move all others to the setting file.
Take a look at the MSDN documentation of <appSettings> node. In the "file" description, notice the phrase "In the .NET Framework version 2.0, you can now include configuration settings in a separate file for all configuration elements that support the configSource attribute". The possibilities are truly endless!
configSource
Happy coding,.