服务器端breeze.js中的验证和安全性

时间:2013-06-03 08:58:52

标签: breeze unit-of-work

我正在尝试使用breeze.js保存一些实体。 Breeze工作正常,它会根据需要保存所有更改。但是,我无法验证并确保授权是服务器端。从我到目前为止收集的内容来看,我想要做到这一点的唯一方法是检查传递给保存包的JObject并在服务器端构建相应的对象。我必须这样做(而不是依赖Breeze.SaveChanges,因为我在服务器端有一些逻辑)。我该怎么做呢?我如何构建Breeze.WebApi。 SaveResult? 任何其他解决这个问题的方法的想法也非常受欢迎

3 个答案:

答案 0 :(得分:2)

这应该通过实施自定义EFContextProvider来完成。

下面的代码为Northwind数据库实现了自定义EFContextProvider,并直接从documentation on the breeze.com website获取。

    public class NorthwindContextProvider: EFContextProvider<NorthwindIBContext>  {
    public NorthwindContextProvider() : base() { }

    protected override bool BeforeSaveEntity(EntityInfo entityInfo) {
      // return false if we don’t want the entity saved.
      // prohibit any additions of entities of type 'Role'
      if (entityInfo.Entity.GetType() == typeof(Role)
        && entityInfo.EntityState == EntityState.Added) {
        return false;
      } else {
        return true;
      }
   }

    protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) {
      // return a map of those entities we want saved.
      return saveMap;
    }
  }

答案 1 :(得分:2)

@ jaq316是正确的:a custom EFContextProvider是拦截来自客户端的更改的地方。它是授权和验证它们的地方。 documentation has more details。{{3}}。它的本质是您在BeforeSaveEntityBeforeSaveEntities虚拟方法的覆盖范围内仔细检查建议的更改;或者,您可以将处理程序附加到BeforeSaveEntityDelegateBeforeSaveEntitiesDelegate

答案 2 :(得分:1)

所以这是我对这个的想法,因为我根本没有使用ContextProvider。我正在利用SQL后端和Ninject将存储库依赖注入到我拥有的每个控制器中。我有比“Todos”的演示更多的项目,并且还需要单独的控制器和存储库。如果我创建了像breeze docs所示的ContextProvider,我将有一个ContextProvider文件,其中包含所有实体。这将是巨大的。如果我将它们分成不同的上下文,我会在所有覆盖中复制代码。

这是ContactFormController.cs中的Save Changes方法:

             [HttpPost]
    public SaveResult SaveChanges(JObject saveBundle)
    {
        var sr = new SaveResult() { KeyMappings = new List<KeyMapping>(), Entities = new List<object>()};
        dynamic entity = saveBundle["entities"][0];
        ContactForm form = entity.ToObject<ContactForm>();
        EntityState state = entity.entityAspect.entityState;

        switch (state)
        {
            case EntityState.Added:

                KeyMapping mapping = new KeyMapping(){EntityTypeName = typeof(ContactForm).ToString(), TempValue = form.Id };
                var validationErrors = _contactFormService.ProcessContactForm(ref form).Cast<object>().ToList();

                //if we succeed then update the mappings
                if (validationErrors.Count == 0)
                {

                    //setup the new mappings
                    mapping.RealValue = form.Id;
                    sr.KeyMappings.Add(mapping);

                    //link the entity
                    sr.Entities.Add(form);
                }
                else
                {
                    sr.Errors = validationErrors;
                }

                break;
        }

        return sr;
    }

我在客户端保存之前动态更改端点,以便我的webapi中的每个控制器都有一个SaveChanges()方法。然后我调用适当的存储库来根据需要处理后端函数。这样我可以根据注入的repo运行模拟代码或实际的SQL更改。

如果它们是表单处理的错误,那么我们将自定义列表列表转换为List并将其分配给SaveResult的Errors属性。如果没有错误,我们会发回新的密钥映射以在客户端上更新。

理想情况下,我希望减少此控制器中的所有代码,并可能将其抽象为实用程序方法,以便每个控制器中的重复次数更少。我喜欢这种方法,因为那时我可以创建普通的存储库,而不是让它们依赖于ContextProvider。微风独立于那一点。