我一直在尝试并且未能找到使用Entity Framework Code First加密SQL数据的好方法。我必须在前面加上我在Azure中托管并且无法访问本机SQL加密。
从SecurEntity获取页面,我已经完全实现了一种利用SaveChanges和ObjectMaterialized来处理实体加密/解密的方法,但在测试中我发现这太难以使用了。< / p>
以下是一些实施的示例:
public override int SaveChanges()
{
var pendingEntities = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
.Where(en => !en.IsRelationship).ToList();
foreach (var entry in pendingEntities) //Encrypt all pending changes
EncryptEntity(entry.Entity);
int result = base.SaveChanges();
foreach (var entry in pendingEntities) //Decrypt updated entities for continued use
DecryptEntity(entry.Entity);
return result;
}
void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
DecryptEntity(e.Entity);
}
我已经看过其他帖子通过辅助属性手动加密/解密,如下所示:
public Value { get; set; }
[NotMapped]
public DecryptedValue
{
get { return Decrypt(this.Value); }
set { this.Value = Encrypt(value); }
}
这肯定会奏效,但我发现这种方法不太理想。使用这种方法时,所有开发人员都必须浏览所有加密属性,以找出可以使用的属性。
最理想的解决方案是让我能够在数据访问级别覆盖每个值的获取/设置。有没有办法做到这一点?如果没有,我如何使用Entity Framework - Code First实现数据加密,以便易于维护和使用?
答案 0 :(得分:11)
我有个好消息。我使用SaveChanges / ObjectMaterialized方法遇到的不稳定性是由于在DbContext实际执行保存之前不会调用DetectChanges()
。
在我从DetectChanges()
提取已添加/已修改记录之前,我可以通过调用ObjectStateManager
来解决此问题。这清除了导致加密行为不一致的任何对象状态怪异。
结果代码为:
public override int SaveChanges()
{
var contextAdapter = ((IObjectContextAdapter)this);
contextAdapter.ObjectContext.DetectChanges();
var pendingEntities = contextAdapter.ObjectContext.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
.Where(en => !en.IsRelationship).ToList();
foreach (var entry in pendingEntities) //Encrypt all pending changes
EncryptEntity(entry.Entity);
int result = base.SaveChanges();
foreach (var entry in pendingEntities) //Decrypt updated entities for continued use
DecryptEntity(entry.Entity);
return result;
}
编辑 - 添加了一个示例DataContext,以查看我的加密所有实体的端到端解决方案。注意:您不必使用自定义属性来加密属性。 Source