对于我们开发大型应用程序的客户,如果您愿意,所有用户都可以看到对方数据。
现在突然客户说他们只希望属于同一组织的用户能够查看彼此的数据。
所以我们想出了这个数据模型:
现在的问题是:如何最好地分离数据?
这是我看到的唯一选择:
但我觉得额外的加入(我们有大约20个需要额外加入的表)是非常昂贵的。
我希望我们可以考虑其他一些最佳实践或解决方案。
PS:这是一个使用Java / JSF / Seam开发的Web应用程序(但我不知道这是否相关)
更新
我想澄清一些事情。我的意图不是安全而是表现。我们已将组织的外键添加到具有共享数据的所有相关表中,并且我们正在使用用户的登录组织来过滤数据。
我想知道的是,这是一个很好的架构解决方案(内连接)还是我们应该做的其他事情(即:加载所有共享数据,并在内存中过滤而不是sql join)。
答案 0 :(得分:4)
您必须了解持久层和应用层之间的区别。
如何定义数据库表并不重要,因为任何具有数据库访问的人都可以访问所有用户数据。 的重要性在于您如何定义应用程序中的行为。
只应出于性能原因而更改数据库设计,不以确保安全性 - 应在应用程序中处理。
答案 1 :(得分:1)
我认为最好的模式是仅通过Web应用程序公开用户详细信息,因此在这一点上限制了向每个用户公开的数据。这将允许您在应用程序内部构建所需的安全性。
或者,如果您允许直接访问数据库,则需要为每个组织或用户创建登录/用户(取决于所使用的数据库),然后将这些登录/用户实体的访问权限限制为参数化存储过程,而不是基表。这会将安全性推回到数据库,这样风险更大但仍然可行。
对于支持组织列的元更改,参数化存储过程将非常简单:
select @organizationId = organizationId from User where User.id = @currentUserId
select * from User where organizationId = @organizationId
(取决于sql风格,你需要包含一些实体,例如``User ,[User]等)
答案 2 :(得分:0)
我认为没有理由组织必须“加入”。
如果您的'数据'表都有OrganizationID列,那么您可以从用户查找'organizationID',然后将其作为条件添加到连接中。
EX:
select @OrganizationId = organizationId from User where User.id = @currentUserId
select * from datatable a .... where .... AND a.organizationID = @organizationID
请参阅;没有加入。
关于性能,有不同类型的连接,SQLServer允许您提示连接类型。所以在某些情况下,合并连接是最好的,而在这种情况下,循环连接是最好的。不确定MySQL中是否有这些选择。
对于需要连接或条件的表的所有(见上文),有一个逻辑答案和一个实现答案。实现答案取决于您的索引。如果您可以通过添加该条件来限制数据集,那么您将受益。但是如果与已经过滤的其他表的连接在减少行方面做得更好,那么条件将毫无价值(或者最坏的情况,它将使用错误的索引)。假设你的连接和条件列都有索引。
逻辑上,只有完全依赖于由organizationID过滤的表的数据才需要额外的条件。如果你有一个汽车餐桌和carparts表,那么你只需要过滤汽车餐桌。除非由于某种原因你不需要加入car table进行某些连接,在这种情况下你也需要在parts表上使用organizationID。