【发布时间】: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 它可能值得看看他们的解决方案,而不是自己动手。
标签: sql-server security sql-server-2012 extended-properties