One of the many nice features of ASP.NET 2 is the ability to have an arbitrary section of a Web.config file encrypted, and to decrypt the content at runtime in a way that is transparent to your application code (i.e. you don't have to worry about it).
This is a big step forward....provided, of course that you have the ability to run command line utilities on the host machine, since that is a required part of the process.
Sadly, that excludes anyone whose site is hosted on a server to which they in fact have no direct access at all, which is the case of course for many people.
So we are left with having to decrypt connection strings explicitly through code, just as in ASP.NET 1.1...but it's not that easy.
The various ASP.NET 2.0 Providers provided out of the box obtain their connection strings as part of their initialisation code, and would work particularly well with one that is, well, gibberish.
Well, first things first: I strongly suggest that in this sort of situation you decrypt the connection string or strings at application start up, and then cache it indefinitely (this is actually a case where old-style Application variables are perfectly fine).
One might think that all that then remained in order to provide say SqlMembershipProvider with your shiny new connection string all you'd have to do is derive a class from it (and you thought that inheritance stuff was just for answering questions at job interviews about OO...) and override the _sqlConnectionString field (which is what it's called in the cases I've checked). Unfortunately it's still not that simple: _sqlConnectionString is a private field, not protected, so it is not exposed in a derived class.
This is where the magic of Reflection comes in: you can use a FieldInfo object to obtain a reference to _sqlConnectionString (even though it's private), and then use the SetValue method of the aforementioned FieldInfo object to set the value to your freshly decrypted connection string. Here's a complete example for a class deriving from SqlMembershipProvider:
public class MyMembershipProvider:SqlMembershipProvider
{
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
FieldInfo sqlConnectionStringField;
sqlConnectionStringField = typeof(SqlMembershipProvider).GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
sqlConnectionStringField.SetValue(this, HttpContext.Current.Application["slightlySecretConnectionString"]);
}
}
To do the same for SqlRoleProvider you use almost identical code, except that (predictably) you inherit from SqlRoleProvider, and typeof(SqlMembershipProvider) becomes typeof(SqlRoleProvider).
It's obviously not an ideal solution, but it's better than nothing.