您似乎正在应用记录级别的安全性。
最好的方法是拥有一个安全表(每个表States
,City
和Branch or Post Code
catch-all 权限All
都有自己的 ID - 这应该是尽可能小的数字数据类型,但为了清楚起见,我将其视为文本回答):
UserID TableID RecordID
RecordID
可以为空。
如果输入单个记录:UserID = @x TableID = 'All' RecordID = Null
,则该用户有权访问所有数据。
如果用户被授予访问州数据的权限:UserID = @x TableID = 'States' RecordID = 1
,则该用户有权访问与 ID = 1 的州相关的所有城市和邮政编码。
如果授予用户访问城市数据的权限:UserID = @x TableID = 'City' RecordID = 1
,则该用户可以访问与 ID = 1 的城市相关的所有邮政编码。
如果用户被授予访问分支或邮政编码数据的权限:UserID = @x TableID = 'Branch or Post Code' RecordID = 1
,则该用户只能访问 ID = 1 的分支或邮政编码。
如果您愿意,您可以添加一个额外的位字段:Deny
,当等于 1 时,将拒绝访问该记录。这在与此类似的场景中很有用:在城市“X”中,用户可以访问除少数邮政编码之外的所有邮政编码,因此您将授予对该城市的访问权限并拒绝访问排除的邮政编码。
当然,如果没有权限记录,就没有访问权限。
如果您想要一些更简单的东西,您可以为每个地理表创建一个权限表,并且用户记录可以有一个“所有访问权限”位字段。
您需要生成 SQL 以根据权限表中的数据过滤您的地理表。
编辑:
考虑到提问者对数据大小、编程简单性和数据维护难易程度的担忧:
这种方法旨在最大限度地减少数据开销。当用户被授予(或拒绝)访问整个数据集或数据树的整个子树的权限时,只需要一个权限记录。只有当用户被授予对分支的访问权限时,每个用户的权限记录数才会变得非常高。
将三个表中的相关数据聚合到权限 UI 并将权限应用到数据中涉及到一些编码工作,但是这不应该超出一个相当称职的程序员创建或理解的能力,特别是如果正确评论和记录。如果预计将应用程序交给的程序员不是相当称职的,则可以将权限拆分为每个表的单独权限集,但这对 DBA 来说可能不太有用。
由于这种方法应该最大限度地减少与每个用户相关联的权限记录的数量,因此与纯粹在最低级别的仅授予权限结构相比,维护要容易得多,后者会生成数以千计的权限记录,DBA 必须这样做保持,这种方法也更容易出现包含和遗漏的错误。我描述的方法可能只需要每个用户的少数权限记录,而不是数千条。