SQL Server 数据库中使用扩展属性的动态行级安全性

Posted

技术标签:

【中文标题】SQL Server 数据库中使用扩展属性的动态行级安全性【英文标题】:Dynamic Row Level Security In a SQL Server Database Using Extended Properties 【发布时间】:2016-03-15 09:41:19 【问题描述】:

我们需要为客户提供对暂存数据库的访问权限,以便他们可以将数据提取到自己的服务器中,但每个表都包含所有客户数据。所有表都有一个“CustomerID”列。客户只能看到 customerID 与他们相同的行。

我不是在寻找为每个客户创建单独的数据库或视图的建议,因为这两个建议都是高维护和低效率的。

我的解决方案必须使用:

100GB 数据库 400 个表 从核心事务数据库每 30 分钟更新一次 每季度架构更改(应用程序处于持续开发中)。

谁能给我一个明确的答案,说明为什么以下方法不安全或不起作用?:

我为每个客户设置了一个数据库用户,他们的 customerID 作为扩展属性。

我创建了每个表的视图,该视图从表中动态选择 *,其中 customerID 列与登录用户的扩展属性 CustomerID 相同。代码看起来像这样并且运行良好:

CREATE VIEW [CustomerAccessDatabase].[vw_Sales] 
AS SELECT * FROM [CustomerAccessDatabase].[Sales] 
WHERE [Sales].[CustomerID]= 
         (SELECT CONVERT(INT,p.value) AS [Value] 
         FROM sys.extended_properties
         JOIN sys.sysusers ON extended_properties.major_id=sysusers.[uid] 
         AND extended_properties.name = 'CustomerID' 
         AND sysusers.[SID]=(SELECT suser_sid())
         );
GO

为了提供对视图的访问,我创建了一个通用数据库角色“Customer_Access_Role”。此角色有权访问所有表视图,但拒绝访问数据库表本身。

为了防止用户更改自己的 customerID,我拒绝访问扩展属性,如下所示:

USE [master];
GO
DENY EXEC ON sys.sp_addextendedproperty to [public];
GO
DENY EXEC ON sys.sp_dropextendedproperty to [public];
GO
DENY EXEC ON sys.sp_updateextendedproperty to [public];
GO

最终结果是我只需要一个数据库和一组权限。

要添加新客户,我需要做的就是创建一个新用户,并将其 customerID 作为扩展属性,并将其添加到 Customer_Access_Role。就是这样!

【问题讨论】:

你为什么要这么麻烦?为什么不直接复制数据库,然后删除与该客户无关的所有数据。这似乎是一种非常冗长且冒险的方法来隐藏您不希望他们看到的数据。 嗨坦纳,感谢您的评论。这是一个临时数据库,每 30 分钟更新一次,可能包含数千个事务。我们的少数大客户拥有自己的商业智能团队,他们希望从自己的服务器运行定制的日内报告。他们会保留一个重复的数据库并从共享的临时数据库中更新它。 我会为这些大客户创建一个单独的数据库,期望这些更改能够充分保护您的数据库听起来太冒险了,尤其是当您继续进行更改并且必须记住这样做时跨度> 从 GoldBishop 的回答中复制评论:我很欣赏我的解决方案可能不寻常,但它具有很大的可扩展性优势。该数据库中有 400 个表。如果我只有 10 个客户想要此访问权限,那就是 4000 个视图,每个视图都有不同的用户和不同的权限。如果我给每个客户自己的数据库,我需要在每次有新客户出现时创建一个新的自定义数据库和 ETL 包,并在架构发生变化时维护每个数据库。 我知道您正在寻找适用于 SQL Server 2012 的解决方案,但 Microsoft 正在开发 SQL Server 2016 和 SQL Azure 中的行级安全功能:msdn.microsoft.com/library/dn765131.aspx 它可能值得看看他们的解决方案,而不是自己动手。 【参考方案1】:

我将重申每个人已经说过的内容并总结一下。

    你让你的工作变得比原来更难。 创建一个视图,这只是他们的数据,然后授予他们对该视图的安全访问权限。 或者,将他们的所有数据从“核心”数据库中提取到他们自己的数据库中,并授予他们对该数据的必要访问权限。

【讨论】:

感谢 GoldBishop。我很欣赏我的解决方案可能不寻常,但它具有很大的可扩展性优势。该数据库中有 400 个表。如果我只有 10 个客户想要此访问权限,那就是 4000 个视图,每个视图都有单独的用户和单独的权限。如果我给每个客户自己的数据库,我需要在每次有新客户出现时创建一个新的自定义数据库和 ETL 包,并在架构发生变化时维护每个数据库。 听起来你有一个严重的泡菜。也许是时候对数据进行重构规范化了。我的公司在 3 个实例中支持 50 多个客户。在每种情况下,我们为每个客户提供一个数据库。所有这些都是标准设计,任何模式更改在部署到所有 50 个数据库之前都要经过严格的测试模型。在所有情况下,核心逻辑都是通用的,而不是特定于客户端的,并且是表驱动的。 尊敬的,为什么我的解决方案不适用于您的业务案例? 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review @PVitt,如果您阅读了答案,这是对他问题的回答,请查看我的要点的 #2 和 #3。这不是批评,而是更好的设计实现

以上是关于SQL Server 数据库中使用扩展属性的动态行级安全性的主要内容,如果未能解决你的问题,请参考以下文章

如何摆脱 SQL Server 2000 中的扩展表属性?

从扩展属性中获取元数据 (SQL Server)

从 C# 检索 SQL Server 扩展属性

sql server 动态行转列

数据库原理与应用(SQL Server)笔记 第十一章 游标

是否可以在 SQL Server 中查询空扩展属性?