我只想弄清楚在Breeze中保存更改时我需要在服务器端实现多少安全性。特别是,我正在思考恶意用户如何手动破解SaveChanges请求或破解客户端中的javascript,以绕过我的正常业务规则 - 例如,恶意更改我的实体上的外键ID。
我想确切地了解我需要关注安全工作的确切位置;我不想浪费时间实现不需要的安全层。
我在服务器端使用Breeze和.net以及Entity Framework。
这是一个微不足道的例子。 ObjectA
引用了ObjectB
,ObjectA
归特定User
所有。所以,我的数据库看起来像这样:
ObjectA:
Id ObjectB_Id SomeField User_Id
1 1 Alice's ObjectA 1
2 2 Bob's ObjectA 2
ObjectB:
Id SomeOtherField
1 Foo
2 Bar
User:
Id Name
1 Alice
2 Bob
从这个模型中,我的安全问题是:
ObjectA
ObjectA
指向Bob的ObjectB
。User_Id
上的ObjectA
更改为Alice。(1)的解决方案是微不足道的;我确保我的SaveChanges方法具有[Authorize]
属性。
我可以轻松使用Fiddler构建一个SaveChanges请求来重现问题2到4 - 例如,我可以构建一个请求,将Alice
的ObjectA更改为指向Bob的{{ {1}}。这就是消息内容的样子:
ObjectB
正如我所料,当服务器端没有实现安全性时,这会将"entities":
[
{
"Id":1,
"ObjectB_Id":2,
"SomeField":"Alice's ObjectA",
"User_Id":1,
"entityAspect":
{
"entityTypeName":"ObjectA:#MyNamespace",
"defaultResourceName":"ObjectAs",
"entityState":"Modified",
"originalValuesMap":
{
"ObjectB_Id":"1"
},
"autoGeneratedKey":
{
"propertyName":"Id",
"autoGeneratedKeyType":"Identity"
}
}
}
],
的更新值持久存储到数据库中。
但是,我还确认,如果ObjectB_Id
中的ObjectB_Id
没有条目,那么即使我更改了originalValuesMap
的主要内容它未在数据库中更新的消息。
所以,我认为这意味着我需要在服务器上遵循的一般安全规则是:
[2013年7月4日修改 - 为清晰起见而重写]
一般来说:
For" Unchanged"属性(不在originalValuesMap上的属性):
对于已更改的属性(同样位于originalValuesMap上的属性):
业务规则可能会阻止更改特定属性。如果是这种情况,我们应该对每个这样的规则进行检查。
如果允许更改某个值,并且它是外键,我们应该执行安全检查以确保会话标识允许使用新值
我们不得使用originalValuesMap中的任何原始值,因为这些值可能已被篡改
[编辑完结]
假设这些规则是正确的,我想有几个选项可以围绕更改的外键实现安全性:
ObjectB_Id
;我需要去数据库(或其他可信来源,例如会话Cookie)将这些规则应用于我上面提到的安全问题,
安全问题(2)。我需要针对当前在数据库中的originalValuesMap
上的User_ID
检查会话中的用户身份。这是因为我无法信任请求中的User_ID,即使它不在ObjectA
中。
安全问题(3)。如果业务规则允许更改originalValuesMap
,我需要检查谁拥有ObjectB
的新值;我将通过从数据库中检索指定的ObjectB来完成此操作。如果此ObjectB_Id
不归ObjectB
所有者所有,我可能想拒绝这些更改。
安全问题(4)。如果业务规则允许更改ObjectA
,则(2)已涵盖此内容。
所以,真的,我正在寻找确认我正在思考的问题。
答案 0 :(得分:2)
我不认为你“过于复杂化”
读过这篇文章的人可能会想“哇......那是很多工作......微风的东西一定是不安全的”。
这是很多工作。但是Breeze并不是让它变得困难。这是现有每个Web应用程序的必要思路。身份验证只是第一步......最简单的步骤......保护应用程序。
您不应该信任任何客户端请求...即使客户端已通过身份验证。这意味着确保客户端有权发出请求,并且进入和退出服务器的内容与客户端声称要执行和允许执行的内容一致。这些是适用于所有Web应用程序的一般原则,而不仅仅是Breeze应用程序。坚持这些原则在微风中并不比任何其他技术更难。
您可能忽略了一个微风技术性。 EFContextProvider.Context
应该只保存要保存的实体;请勿使用它来检索原始实体。您需要单独的DbContext
来检索原始实体,以便与客户端中的更改集实体进行比较。
我们正在研究样品,以展示处理您所描述问题的方法。例如,我们建议(和演示)一个插入BeforeSaveEntitiesDelegate
的“验证规则引擎”;这种“引擎”方法可以更容易地编写一堆服务器端规则并自动应用它们。
我们的样本和指导尚未准备好发布。但是它们正在出现。
同时,按照你在这里描述的直觉行事。有关您进度的博客。告诉我们......我们很高兴能够突出你的帖子。
答案 1 :(得分:0)
我一直在寻找同一事项的指导,我很高兴找到你的精彩分析。在我看来,我们的问题的答案是不同的,假设我们正在讨论的应用程序将由多个模块组成,并且寿命超过一年。
如果规则变得过于复杂,则意味着我们可能会使用不恰当的方法。我相信很多优秀的开发人员都会应对这些规则,但令人遗憾的是,我们大多数同行要么弄错了,要么会在压力下忘记其中的一些。
我要说我们需要回到Fowler,Evans和Nilssons的出版物,并在他们之后重复说,在更大的应用程序中(这些具有强大的安全要求)实体模型不应该暴露给它客户端(除了安全性之外的其他原因 - 例如可维护性)。
另一方面,值得关注Greg Young和Udi Dahan后来提出的这些原创想法的修订。这些本质上说,阅读模型不一定也不常与写“数据”的模型相同。
总而言之,我要说基本规则应该是不要使用Breeze进行写作并将DO用于阅读(使用DTO /预测),前提是您不查询“真实”模型但是专为阅读而建的模型(例如视图而不是表格)。
如果您遵循您的域名和用例,并且最重要的是如果您遵循测试驱动方法,那么这一切都很自然地出现了。您是否真的会在遵循测试驱动开发的同时最终获得针对业务规则的BeforeSaveEntities解决方案?