安全评估的适当位置 - 业务逻辑或数据访问

时间:2010-06-21 18:17:57

标签: security linq-to-sql domain-driven-design

请原谅这里的长度......希望我没有过火......

我正在处理我的第一个生产MVC应用程序,我正在努力坚持DDD原则。我遇到了一些与如何处理应用程序的安全性要求有关的问题,并且我认为SO社区是否可以提供一些最佳实践建议。

域名信息

要使用简化说明,此应用程序将包含AffiliateCompaniesUsersCustomers

  • AffiliateCompanies是分层的,因此一个联盟会员可以注册并与其他联盟会员的活动联系在一起。根是提供产品/服务的主要公司。
  • Users都属于关联公司实体。
  • Customers是销售产品/服务的组织。分支机构被分配给客户,使得两个分层无关的分支机构可以分割客户。

安全信息

在应用程序中执行某些操作的权限将基于ACL类型的安排来确定。每个User对象都有一个属性,它是SystemAccessRules的集合,用于确定它们可以执行的操作以及它们的权限范围(它们自己的对象,其关联对象或整个层次结构的对象) 。用户也可以属于角色,这些角色本身具有相同的SystemAccessRules

集合

因此,如果用户登录并希望查看“他们的”客户列表,则该列表可以包括他们被单独分配给的客户,其联盟组织中的任何人被分配给的客户,或者客户任何人在他们的组织或他们的任何子会员组织被分配到。

数据库注意事项

抛开DDD,在某些时候,存储策略必须发挥作用。在这个简单的场景中,表格与上面的对象(包括角色表)对齐,并有一些支持表来支持对象之间的关系:

  • AffiliateCustomers - 此表允许通过将每个实体的PK存储为一对FK来实现关联企业与客户之间的多对多关系,这些FK本身就是此表的复合PK。
  • ACL - 此表存储安全信息,特别是条目的主题(用户或角色),相关操作(例如“CreateCustomer”),权限(允许或拒绝),和范围(他们自己的东西,他们的组织或他们的网络)。

问题......最后

我正在使用存储库和服务的组合。我正在尝试将业务逻辑保留在服务中以及存储库或数据库之外,但由于此处的安全设计,对“他们的”客户列表的简单请求可能非常繁重,尤其是在数据集增长时。我试图在可能的情况下使用Linq,但这种架构似乎并不适合。在我看来,这是我的选择:

  1. 接受请求用户作为服务方法的参数(或通过上下文确定),并让服务方法通过多个查询填充列表到Linq存储库。这需要拉动客户列表,然后遍历每个客户以发出另一个查询来提取ACL数据,然后使用该数据根据权限过滤第一个列表。层次结构问题需要一些花哨的Linq脚步(如this),如果可能的话。 即使可以使层次结构问题起作用,似乎此解决方案也不会很好地运行......

  2. 接受请求用户作为参数,但将其和所需权限(例如“查看客户”)传递给存储库,以便通过使用多个EXISTS子句的存储过程从数据库中检索适当的数据在CTE查询中,可以解释数据的分层性质以及检查角色和用户安全性的需要 这会给数据库带来相当多的逻辑,这看起来非常反DDD,而且通常很糟糕。

  3. 我更倾向于第二种选择,但这可能是因为在我过去的项目中我是如何做到的。我甚至不确定我的设计总体上是否在正确的轨道上(在过去,权限声明是使用位标志完成的,因此使用按位运算符进行数据库查询更加容易)。

    是否有人遇到类似情况,如果有,您是否可以对所追求的解决方案的性能和可维护性发表评论?我想坚持高尚的编程原则,但不以牺牲简单性和常识为代价。

1 个答案:

答案 0 :(得分:0)

您是否考虑过使用specification pattern将业务规则传递到数据访问层?

该服务构造一个它传递给存储库的规范树。存储库将规范转换为Expression<Func<Customer, bool>>,并将其传递给IQueryable<Customer>.Where(...)。当存储库实现集合时,例如,通过调用ToList(),业务规则被转换为SQL并在数据库服务器上执行。

上次检查时,LINQ to SQL不支持CTE,因此您可能需要使用视图来展平层次结构。