除了我之前关于 Entity Framework 的问题。我的目的是在保存到 DB 之前加密字段并在从 DB 读取之前解密字段。我有从表 User 生成的类(User.cs)(具有 UserName 属性(要加密)并且我创建了一个单独的类 SecureUser with UserName如前所述加密/解密的属性。但我不确定如何将这个新的 SecureUser 类映射到 DB 而不是以前的 POCO 类用户。当我用 SecureUser 类中的 UserName 替换 UserName 时,我的 Linq 查询失败。我尝试做同样的事情部分类的事情,同样的事情发生。 任何建议将不胜感激!
[Table("Users")]
public class User
{
#region database table column mapped fields
[Key]
[Required]
public Int32 UserID { set; get; }
[Required]
[MaxLength(50)]
public String UserName { set; get; }
[Required]
public Int32 CustID { set; get; }
//created the separate class as
public class SecureUser // UserViewModel
{
//
private readonly User _user;
public SecureUser(User user)
{
_user = user;
}
public string UserName
{
get { return Decrypt(_user.UserName); }
set { _user.UserName = Encrypt(value); }
}
最佳答案
我非常喜欢任何依赖于属性的解决方案。
假设您有一个实体类,其中包含一个或多个要加密存储在数据库中的属性。只需添加 [Encrypted]
属性即可。
[Encrypted]
public string EncryptedProperty { get; set; }
现在创建一个自定义的 DbContext,它可以为您动态地进行加密/解密:
public class MyDB : IdentityDbContext<User>
{
//DBSet properties go here
public MyDB()
{
((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += new ObjectMaterializedEventHandler(ObjectMaterialized);
}
#region Encryption
public override int SaveChanges()
{
var contextAdapter = ((IObjectContextAdapter)this);
contextAdapter.ObjectContext.DetectChanges(); //force this. Sometimes entity state needs a handle jiggle
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;
}
public override async Task<int> SaveChangesAsync(System.Threading.CancellationToken cancellationToken)
{
var contextAdapter = ((IObjectContextAdapter)this);
contextAdapter.ObjectContext.DetectChanges(); //force this. Sometimes entity state needs a handle jiggle
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);
var result = await base.SaveChangesAsync(cancellationToken);
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);
}
private void EncryptEntity(object entity)
{
//Get all the properties that are encryptable and encrypt them
var encryptedProperties = entity.GetType().GetProperties()
.Where(p => p.GetCustomAttributes(typeof(Encrypted), true).Any(a => p.PropertyType == typeof(String)));
foreach (var property in encryptedProperties)
{
string value = property.GetValue(entity) as string;
if (!String.IsNullOrEmpty(value))
{
string encryptedValue = EncryptionService.Encrypt(value);
property.SetValue(entity, encryptedValue);
}
}
}
private void DecryptEntity(object entity)
{
//Get all the properties that are encryptable and decyrpt them
var encryptedProperties = entity.GetType().GetProperties()
.Where(p => p.GetCustomAttributes(typeof(Encrypted), true).Any(a => p.PropertyType == typeof(String)));
foreach (var property in encryptedProperties)
{
string encryptedValue = property.GetValue(entity) as string;
if (!String.IsNullOrEmpty(encryptedValue))
{
string value = EncryptionService.Decrypt(encryptedValue);
this.Entry(entity).Property(property.Name).OriginalValue = value;
this.Entry(entity).Property(property.Name).IsModified = false;
}
}
}
#endregion Encryption
}
然后添加一个类
class Encrypted : Attribute
{
}
关于c# - 使用公开加密/解密值的单独类通过 Entity Framework 加密解密数据 : Linq statements fails,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27712088/