是否有 .Net 属性会告诉 Breeze 完全忽略某个属性?
我知道使属性受到保护是一种将其隐藏在 Breeze 中并防止其序列化的方法,但是如果我希望它保留public
呢?
设计一种简单、可维护的方法让 EF 生成的元数据对客户端说一件事,而对 EF 本身说另一件事是很棘手的。
但是,如果您愿意拥有两个DbContext ,则可以这样做:用于服务器端模型操作的“真实” DbContext和另一个严格用于客户端元数据生成的DbContext 。
这并不像听起来那么困难。我在 DocCode 中尝试过这样的事情。我创建了一个NorthwindMetadataContext
继承自NorthwindContext
. 它隐藏了废弃的CustomerID_OLD
属性。
这是整个 DbContext:
公共类 NorthwindMetadataContext : NorthwindContext { 受保护的覆盖无效 OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Customer>().Ignore(t => t.CustomerID_OLD); } }
你没看错!我只是添加了一条 EF Fluent API 指令来CustomerID_OLD
隐藏NorthwindMetadataContext
.
它仍然在Customer
type 上,并且仍然为 base 所知NorthwindContext
。这意味着CustomerID_OLD
当您使用 查询时,查询将返回该属性,NorthwindContext
但在您使用 查询时不会返回该属性NorthwindMetadataContext
。
当然,您只使用NorthwindMetadataContext
来为 Breeze 客户端生成元数据。您的所有服务器逻辑继续使用“真实”的基础NorthwindContext
NorthwindRepository
我通过更改实现Metadata
属性的方式来确保会发生这种情况:
公共字符串元数据 { 得到 { var metaContextProvider = new EFContextProvider<NorthwindMetadataContext>(); 返回 metaContextProvider.Metadata(); } }
所有其他成员对“真实” DbContextNorthwindRepository
使用EFContextProvider:
私有只读 EFContextProvider<NorthwindContext> _contextProvider = new EFContextProvider<NorthwindContext>();
这就像一个魅力。据客户所知,该CustomerID_OLD
物业不存在。
尽管您已对 Breeze 客户端隐藏了该属性,但该属性仍保留在服务器端实体类型上,并且因为我们使用“真实”DbContext 进行查询和保存操作,您可以在CustomerID_OLD
查询中看到该属性通过线路传输结果有效载荷。
为了防止这种情况发生,您可以将 JSON.NET 序列化程序[JsonIgnore]
属性添加到Customer.CustomerID_OLD
模型中的属性(如果您不想使用 JSON.NET 序列化属性污染模型,则可以使用其他 JSON.NET 配置选项)。
再次运行,CustomerID_OLD
不再序列化。该CustomerID_OLD
属性现在对客户端完全不可见,但仍然可以在服务器上的模型中访问。
隐藏在元数据中的属性对 Breeze 客户端是隐藏的……但对世界是隐藏的。因为您希望该属性在 SERVER-SIDE TYPE 上可用,所以即使您在序列化完整类型时隐藏了该数据,邪恶的客户端(不是 Breeze 客户端)仍然可以通过投影获取该数据。
以下查询 URL 返回投影数据,其中包含CustomerID_OLD
查询整个Customer
对象时不可见的数据。
http://localhost:47595/breeze/Northwind/Customers?$filter=startswith(CompanyName,'C') eq true&$select=CustomerID_OLD,CompanyName
这是一些结果:
{ "$id": "1", "$type": "_IB_em9q7XTURqKf5bmIrAQD0bJ6f_po[[System.String, mscorlib],[System.String, mscorlib]], _IB_em9q7XTURqKf5bmIrAQD0bJ6f_po_IdeaBlade", "CustomerID_OLD": "CACTU", "CompanyName": "Cactus Comidas para llevar" },
也许更严重的是,POST 可以更新到“SaveChanges”请求的有效负载中的隐藏属性。
与敏感数据一样,您必须检查每个保存请求,以确保允许用户保存OriginalValues
集合中标识的每个更改的属性值。
如果您有安全方面的顾虑,我觉得将DTO用于携带不得暴露给未经授权的客户端的数据的类型会更安全。我不喜欢每种类型的 DTO。这是矫枉过正,可能会破坏生产力。但对于具有重要保密要求的实体类型,我确实喜欢它们。
我还没有决定是否将这个示例保留在已发布的 DocCode 中或将其存储在我的私人保留中。这是一个很酷的技巧。
我担心的是人们会认为这种技术是一种隐藏机密数据的安全方法,而事实并非如此。隐藏您宁愿隐藏的数据很好。但如果它必须远离电线,你最好使用 DTO。
让我知道我所描述的内容是否足够清楚,您可以在没有具体示例的情况下继续进行。
如果您使用 Json.Net 序列化程序(Breeze.WebApi 默认),您可以使用 JsonIgnoreAttribute,在此处描述