在您的某个实体上说,您有一个属性,当您需要保存到数据库时,它需要加密,但是当您在代码中处理它时,您只想将其视为纯文本。
现在,我有这个设置:
public class MyEntity
{
[SecureStringAttribute]
public string SecureString {get;set;}
}
我的DbContext,这就是"魔法"发生的情况。
public MyDbContext()
: base("conn")
{
((IObjectContextAdapter)this).ObjectContext.SavingChanges += ObjectContextOnSavingChanges;
((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContextOnObjectMaterialized;
}
private void ObjectContextOnObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
DecryptSecureString(e.Entity);
}
private void ObjectContextOnSavingChanges(object sender, EventArgs e)
{
EncryptSecureStrings(sender as ObjectContext);
}
private void DecryptSecureString(object entity)
{
if (entity != null)
{
foreach (
PropertyInfo propertyInfo in
EntityFrameworkSecureStringAttribute.GetSecureStringProperties(entity.GetType()))
{
string encryptedValue = propertyInfo.GetValue(entity) as string;
if (!string.IsNullOrEmpty(encryptedValue))
{
string decryptedValue = EncDec.Decrypt(encryptedValue);
propertyInfo.SetValue(entity, decryptedValue);
}
}
}
}
private void EncryptSecureStrings(ObjectContext context)
{
if (context != null)
{
foreach (ObjectStateEntry objectStateEntry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Where(x => x.Entity != null))
{
object[] data = new object[objectStateEntry.CurrentValues.FieldCount];
objectStateEntry.CurrentValues.GetValues(data);
PropertyInfo[] properties =
EntityFrameworkSecureStringAttribute.GetSecureStringProperties(objectStateEntry.Entity.GetType());
foreach (PropertyInfo propertyInfo in properties)
{
string currentValue = objectStateEntry.CurrentValues[propertyInfo.Name] as string;
if (!string.IsNullOrEmpty(currentValue))
{
int index = objectStateEntry.CurrentValues.GetOrdinal(propertyInfo.Name);
string newVal = EncDec.Encrypt(currentValue);
objectStateEntry.CurrentValues.SetValue(index, newVal);
}
}
}
}
}
直截了当我只是在保存和加载时加密/解密字符串。但是,如果我执行以下操作:
MyEntity entity = new MyEntity(){SecureString= "This is secret!!"};
dbContext.SaveChanges();
此时entity.SecureString
已加密,对此对象的任何进一步使用都将不正确。
答案 0 :(得分:3)
您可以使用一对属性(一个始终加密的属性,一个永远不会加密的属性)来代替一个将被翻转到/从加密的单个属性。
public class MyModel
{
public string EncryptedInfo { get; set; }
public string PlainTextInfo {
get
{
return Decrypt(EncryptedInfo);
}
set
{
EncryptedInfo = Encrypt(value);
}
}
在模型构建器中,忽略未加密的属性:
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyModel>()
.Ignore(m => m.PlainTextInfo);
}
}
只要您不熟悉应用程序中其他地方的加密属性,它就可以正常运行。
答案 1 :(得分:2)
添加属性UnsecuredString
并使用[NotMapped]
属性进行装饰。
实现getter和setter以解密和加密SecureString数据。
答案 2 :(得分:0)
感谢你们的建议,我决定同意这个......我总是在发布SO之后想出来。
我想采用一种方法,我不必担心添加NotMapped属性等,虽然我知道这很好。
只需覆盖此类的SaveChanges方法。
public override int SaveChanges()
{
int result = base.SaveChanges();
foreach (DbEntityEntry dbEntityEntry in this.ChangeTracker.Entries())
{
DecryptSecureString(dbEntityEntry.Entity);
}
return result;
}
所有这一切都是在调用SaveChanges之后,我们回过头去除了我们需要的任何东西。
由于