【发布时间】:2015-11-04 02:54:02
【问题描述】:
我正在设计一个限制对某些对象的访问的数据库。我和我的同事讨论了解决此问题的不同方法,主要候选人有:1)隐式访问和 2)显式访问
为了说明,我们假设有以下表格:
User (Id)
ObjectA (Id, ParentId) -- Where ParentId is an ObjectA
ObjectB (Id, ObjectAId)
UserObjectA (UserId, ObjectAId) -- Grants access to an ObjectA
UserObjectB (UserId, ObjectBId) -- Grants access to an ObjectB
隐式方法:
- 因为 ObjectA 作为 ObjectB 的包含实体,如果用户可以访问作为 ObjectB 容器的 ObjectA,那么即使在 UserObjectB 中没有这样的显式记录,他也可以访问包含的 ObjectB。
- 类似地,如果用户有权访问父 ObjectA,则他有权访问所有 ObjectA 后代,即使 UserObjectA 中没有此类记录。
- 此外,如果用户在任一访问授权表中都没有记录,则隐含地他可以访问 ObjectA 和 ObjectB 中的所有记录。
显式方法:
- 要访问 ObjectA 或 ObjectB 记录,用户必须分别在 UserObjectA 或 UserObjectB 中拥有记录。
- 没有记录就等于没有访问权限,句号。
隐式方法有两个好处:1)当用户隐式访问许多对象时节省空间,2)隐式访问所有对象的用户将可以访问将来添加的所有对象,而无需触发在创建对象时插入或处理 sprocs 中的插入。
显式方法的好处是查询更简单、可维护且性能更高。
最初,我们使用隐式方法运行。然而,在进入各种存储过程的实现之后,处理访问的逻辑变成了野兽,并且我们遇到了各种微妙之处,这使得这种方法比显式方法更容易出错。 (请注意,实际场景比简化的示例要复杂一些。)我发现自己不断实现递归 CTE 来确定访问权限,这不允许我(在考虑性能时)抽象出视图中的某些逻辑部分或内联 TVF。所以我必须在许多不同的存储过程中重复和调整容易出错的逻辑。如果有任何变化,我们将面临一项艰巨的维护任务。
那么,我们在使用这种隐式访问方法时犯了错误吗?我肯定会重新考虑,并希望任何有类似设计决策经验的人提供建议。
【问题讨论】: