Breeze 防止恶意数据更改的策略

Breeze 防止恶意数据更改的策略,breeze,Breeze,寻找防止恶意数据更改的方法:userA操纵(编辑或删除)属于userB的数据。因为我们在客户机上创建实体,所以我们需要将它们(或至少其中一些)分配给经过身份验证的用户 例如: var newItem = ds.createNewItem(); newItem.OwnerId(22); //this is the problem that I see. newItem.Name("New Item"); newItem.Description("I just changed your it

寻找防止恶意数据更改的方法:userA操纵(编辑或删除)属于userB的数据。因为我们在客户机上创建实体,所以我们需要将它们(或至少其中一些)分配给经过身份验证的用户

例如:

var newItem = ds.createNewItem();
newItem.OwnerId(22); //this is the problem that I see.    
newItem.Name("New Item");
newItem.Description("I just changed your item!");
... //and so on
ds.saveChanges();
if (entityInfo.Entity.GetType() == typeof(Item)
    && (entityInfo.EntityState == EntityState.Added 
    || entityInfo.EntityState == EntityState.Modified)
    && ((Item)entityInfo.Entity).OwnerId != _currentUserId) {
    return false
    ... //and so on
假设我们知道在API上调用
SaveChanges
的用户的身份,我们如何针对该用户验证实体(新的或修改的)

首先想到的是将
EFContextProvider
子类化,在saveEntity之前覆盖
,并根据用户的身份检查实体
OwnerId
属性。例如:

var newItem = ds.createNewItem();
newItem.OwnerId(22); //this is the problem that I see.    
newItem.Name("New Item");
newItem.Description("I just changed your item!");
... //and so on
ds.saveChanges();
if (entityInfo.Entity.GetType() == typeof(Item)
    && (entityInfo.EntityState == EntityState.Added 
    || entityInfo.EntityState == EntityState.Modified)
    && ((Item)entityInfo.Entity).OwnerId != _currentUserId) {
    return false
    ... //and so on
如果使用这种方法,在新的
EFContextProvider
类的构造函数中建立
\u currentUserId
是否有意义


一个解决这个问题的想法或者更好的方法?

我认为你的思路是正确的。我自己也一直在做这件事,而且走的是同一条路

假设您已经处理了身份验证,并且有一个
IPrincipal
可用。您还拥有一个自定义的
IIdentity
(称之为
AppIdentity
),您可以在其中为经过身份验证的用户存储
UserId

Web Api的base
ApicController
类通过其
User
属性使ambient
IPrincipal
可用。我们将在您的自定义Breeze Web Api控制器中利用这一点,其开头可能如下所示:

[Authorize] [JsonFormatter, ODataActionFilter] public class BreezeApiController : ApiController { private readonly AppContextProvider _context; public BreezeApiController() { // pass 'User' IPrincipal to the context ctor _context = new AppContextProvider(User); } ... // one of the Query action methods [HttpGet] public IQueryable<Foo> Foos() { return _context.Foos } ... public class AppContextProvider : EFContextProvider<AppDbContext> { public AppContextProvider(IPrincipal user) { UserId = ((AppIdentity) user.Identity).UserId; } public int UserId { get; private set; } ... private bool BeforeSaveEntity(EntityInfo info) { var entity = info.Entity; if (info.EntityState == EntityState.Added) { entity.UserId = UserId; return true; } return UserId == entity.UserId || throwCannotSaveEntityForThisUser(); } ... private bool throwCannotSaveEntityForThisUser() { throw new SecurityException("Unauthorized user"); } 现在,您可能希望防止UserA看到UserB的实体。因此,您的自定义
EFContextProvider
可以相应地进行过滤,而不是让每个
Foo
都出门

public DbQuery Foos { get { // Here the 'Context' is your EF DbContext return (DbQuery) Context.Foos .Where(f => f.UserId == UserId); } } 请注意,服务器上的自定义上下文提供程序负责设置添加实体的
UserId
。无论如何,我们都不会相信客户会这么做。当然,它还负责验证修改和删除的实体的
用户ID


希望这有帮助记住,这只是一个草图。真正的交易将更加复杂,并被重构为助手。

谢谢沃德。这非常有帮助,很高兴知道您将以类似的方式处理这个问题。顺便说一句,我开始在控制器中进行处理,这开始变得混乱,所以感谢您朝着正确的方向推动。我将在下个月根据类似这样的查询,做一个面向安全的示例和指导主题。请继续提问并提出问题。