使用自定义EFContextProvider,我想在实体保存之前检查哪些属性已被修改,以便我可以实现:
有关SO的建议使用OriginalValuesMap来确定修改后的属性,请参阅here和here。如果原始值与新值不同,则属性已被修改。但是,这些原始值由客户端提供,因此可以伪造以匹配新值,从而绕过此检查。
我链接的第一个SO问题表明这不是问题,因为如果原始值是以这种方式伪造的,那么这些属性无论如何都不会被保存:
对于我们没有以任何方式使用的任何其他“未更改”属性,我们无需担心它是否被篡改,因为即使它已经被篡改,也不会将篡改的值保留到数据库中
然而,这是不真实的,只要实体上的所有修改后的属性都具有伪造的原始值。例如,以下代码将绕过基于OriginalValuesMap的服务器端安全检查,并仍保存到数据库:
manager.fetchEntityByKey('Employee', 42).then(function (result) {
var employee = result.entity;
employee.Salary(1000000); // do you think HR will notice?
delete employee.entityAspect.originalValues.Salary;
return manager.saveChanges();
});
当Breeze .NET收到实体时,它将实体添加到处于Modified状态的Entity Framework上下文,并且没有标记为已修改的属性,Entity Framework的行为是保存 all 提供的属性值到数据库。
IMO这是EFContextProvider.HandleModified中的一个安全漏洞,它将EF实体状态覆盖为Modified(在该方法中甚至有一条注释警告不要这样做)。在任何情况下,确定哪些属性已更改并即将保存的正确方法是什么?
答案 0 :(得分:0)
在您的上下文中拦截保存并检查它是否合法保存。为了便于解释,假设您要保存RestrictedClass类型的实体,并定义了表格数据库中的表格RestrictedClasses。
public override int SaveChanges()
{
foreach (
var entry in
this.ChangeTracker.Entries()
.Where((e => (e.State == (EntityState) Breeze.WebApi.EntityState.Modified))))
{
if (entry.Entity.GetType() == typeof(RestrictedClass))
{
var entity = entry.Entity as RestrictedClass;
var originalEntities = RestrictedClasses.Where(e => e.Id = entity.Id).toList();
if (originalEntities.Count == 0) continue; // user is trying to add, illegal since it says it's modified, you do different check for EntityState.Added
var originalEntity = originalEntities[0]; // there should be only one, unique ID
//.... now you check differences between entity and originalEntity and decide whether it's legal or not based on user role.