在 SQL Server 2012 SP2 标准版实例中,我在数据库 A 中有一个用户需要能够在该数据库中的模式 foo 中运行存储过程。他们不应该做任何其他事情。例如,他们不应该能够直接从任一数据库中的任何视图或表进行 SELECT。
存储过程从数据库 A 和 B 中的表中选择。我创建了 WITH EXEC AS OWNER 过程。数据库 A 归 sa 所有,sa 具有 sysadmin 角色,因此应该可以访问这两个数据库。我跑了这个:
USE [master]
GO
CREATE LOGIN [foo] WITH PASSWORD=N'foo', DEFAULT_DATABASE=[A]
GO
USE [A]
GO
CREATE USER [foo] FOR LOGIN [foo]
ALTER ROLE [db_executor] ADD MEMBER [foo];
GO
GRANT EXECUTE ON SCHEMA :: [Bar] TO [foo];
然后我以 [foo] 身份连接并执行该过程,但收到错误消息:
消息 916,级别 14,状态 1,过程 GetReport,第 10 行 服务器主体“sa”无法在当前安全上下文中访问数据库“A”。
将 TRUSTWORTHY 设置为 ON 似乎打开的东西比可接受的要多得多。还有其他解决方案吗?
我不愿意将此作为答案发布,因为我没有可使用代码发布的具体示例,但我向 Mark 指出了 Erland Sommarskog 的精彩文章,通过存储过程授予权限,其中有一节是关于使用证书签署过程的。
证书签名似乎是在不打开各种其他安全漏洞的情况下强制通过过程访问数据的正确方法,这可能发生在所有权链接、使用
TRUSTWORTHY
、将用户提升到更高角色或授予他们直接访问表的权限时(从而为他们提供绕过您的程序的途径)。如果时间允许,我将在这里模拟一个示例(不幸的是,今天不会)。