Suppose that your database contains information that is so sensitive that you never want it to get beyond the data layer of your application. You might want the data layer itself to use the data, but it must never get out to the client.
Typical examples would include the password hashes in a customized security system, social security numbers, or credit card numbers. (Your system might let the last few digits of SSNs or credit cards out, but never the whole thing.)
A relatively foolproof way to accomplish this is by hooking the ObjectMaterialized event in the data context. For example, here is a centralized method that gets data from an ADO.NET Entity Framework ObjectContext.
Its first parameter is a delegate the gets something from the database. The second parameter says whether to wipe out the password data before returning the Users record. Because it is true by default, a caller must make a conscious decision to get the password data.
private T GetData<T>(
RetrieveFromDatabaseDelegate<T> del,
bool nullOutPasswordData = true)
{
T returnValue = default(T);
using (MyEntities db = new MyEntities(ConnectionString))
{
if (nullOutPasswordData)
{
db.ObjectMaterialized +=
new ObjectMaterializedEventHandler(GetData_ObjectMaterialized);
}
returnValue = del(db);
// Accept changes in case we wiped out
// the password data.
db.AcceptAllChanges();
}
return returnValue;
}
The event handler is simplicity itself:
void GetData_ObjectMaterialized(
object sender,
ObjectMaterializedEventArgs e)
{
// If the object that has just 'materialized'
// is a Users record, zip the password info.
Users u = e.Entity as Users;
if (u != null)
{
u.PasswordSalt = null;
u.PasswordHash = null;
}
}
Using this approach, you'll be able to hide the sensitive data before ever it starts wandering around your data layer.
I hope you find this tip useful!