Use the protection proxy design pattern to fetch resources and use authentication. You want to access data, either in embedded databases like SQLite and SQLCE or server databases like MySQL. Your code must access the database only when required and authenticated. You want elegant and object-oriented code.
We must look at the protection proxy design pattern. You want a class for database-related code. Let's call it DatabaseLayer.cs. This file contains a class that does all the work with the database, and sends back DataTable or DataSet objects to the rest of the program.
In this database layer file, we need an interface. An interface is a contract that states all classes inheriting from it must implement certain methods. This interface will be used to "connect" the actual database-using code to the proxy class--the protection proxy. Here are some important points.
In other words, the protection proxy inserts a password check before every call to the database layer. The proxy forwards method calls to its inner database object only if that check succeeds. This fulfills several of the requirements listed at the start of this article.
This interface will be shared by the proxy and database classes. It will contain several functions. (Your interface will have more methods than this example.) As a reminder, an interface doesn't need to use the public keyword, and must not contain implementations.
/// <summary>
/// Classes that inherit from this interface must implement at least
/// these two methods!
/// </summary>
public interface IJournalData
{
void InsertNewRow(DateTime dateTime);
DataTable GetSearchResults(string queryString);
}
Next, I will use the interface defined above and implement the protection proxy object. This will sit between the database code itself, and the callers in the user interface. The Authenticate method here is not part of the interface above, but a special method on the proxy.
/// <summary>
/// Our proxy, which meters access to the inner database object.
/// </summary>
public class JournalProxy : IJournalData
{
/// <summary>
/// This member is the database layer that contains the actual
/// SQL code and logic. This starts out null, and will always
/// be null unless it is authenticated with a password.
/// </summary>
JournalLayer _journalLayer;
/// <summary>
/// What our password must be in order to authenticate the user.
/// </summary>
string _password;
/// <summary>
/// Called when the user tries to enter a password and authenticate.
/// </summary>
/// <param name="suppliedPassword">The password supplied by the user.</param>
/// <returns>Whether the attempt succeeded.</returns>
public bool Authenticate(string suppliedPassword)
{
// User sends in the password, and we make sure it is correct.
if (string.IsNullOrEmpty(suppliedPassword) == true ||
suppliedPassword != _password)
{
return false;
}
// Password is correct. Allocate the database layer, and
// setup the connection to the database code.
_journalLayer = new JournalLayer();
return true;
}
/// <summary>
/// Called when the user wants to insert a new record.
/// </summary>
/// <param name="dateTime">The time supplied by the user.</param>
public void InsertNewRow(DateTime dateTime)
{
// In every method that the proxy implements from the interface,
// make sure that the user was authenticated! If not, return.
if (_journalLayer == null)
{
return;
}
// Forward the call to the actual database code.
// We use a C# DateTime object for our time format.
_journalLayer.InsertNewRow(dateTime);
}
/// <summary>
/// Called when the user tries to search the database full-text.
/// </summary>
/// <param name="queryString">The search terms supplied.</param>
/// <returns>The search results in a table.</returns>
public DataTable GetSearchResults(string queryString)
{
if (_journalLayer == null)
{
return null;
}
return _journalLayer.GetSearchResults(queryString);
}
}
Now we have the above proxy code, and the interface as well. I haven't shown the actual database layer, but let's look at how you would use the protection proxy in your user interface code. Let's assume we are using Windows Forms and this code is inside a class that implements a form.
/// <summary>
/// The member variable proxy.
/// </summary>
JournalProxy _journal = new JournalProxy();
/// <summary>
/// Called when the user enter a password and hits return.
/// </summary>
private void PasswordEntered()
{
// This method is called when the user enters a password.
// _journal here is a JournalProxy. We call Authenticate on
// it. If that succeeds, we can show a welcome message.
// Otherwise, complain that the password was incorrect.
if (_journal.Authenticate(passwordTextBox.Text) == true)
{
// Show something from the database.
}
else
{
textBox1.Text = "Password is incorrect";
// Use must enter a new password now.
passwordTextBox.Clear();
}
}
Authenticate is only called when the user enters a password. Elsewhere in your program, you can use your database layer object, such as _journal, without even worrying about passwords. Look at the proxy implementation above--it will simply abort attempts to use the database if the password hasn't been set.
Finally, let's look at what the database-utilizing code itself looks like. This is the hard part--the SQL, all those compatibility issues, etc. The big thing here is that we don't need to worry about passwords because the protection proxy takes care of all of that for us.
/// <summary>
/// Implement the IJournalData methods, but actually do the work and use the SQL
/// with the database. Don't bother with passwords.
/// </summary>
class JournalLayer : IJournalData
{
/// <summary>
/// Implementation of this method from the interface.
/// </summary>
/// <param name="dateTime">User-specified parameter.</param>
public void InsertNewRow(DateTime dateTime)
{
return;
}
/// <summary>
/// User tries to search the database.
/// </summary>
/// <param name="queryString">The search terms.</param>
/// <returns>The result table.</returns>
public DataTable(string queryString)
{
return new DataTable();
}
}
Here we consolidate all the password authentication code in one spot. You can create code that accesses the database without worrying about the password stuff at all. You add the protection proxy object as a layer between the user interface code and the actual database stuff.
Use protection proxies to improve the database layer in your C# program. You can improve efficiency this way by only accessing resources you can use. Protection proxy makes C# applications easier to develop when requiring a password for a database. There are fewer security bugs, and virtually no drawbacks to the protection proxy.
There are fancy words like surrogate that you can use to describe these things, which are probably good for you to know. The term protected is sometimes used instead of protection. I don't know which is more correct, as I have seen both in fairly reputable sources.