我的数据库中有几个存储过程,用于从位于单独数据库中的datamart加载数据。这些程序通常采用以下形式:
CREATE PROCEDURE load_stuff
WITH EXECUTE AS OWNER AS
INSERT INTO my_db.dbo.report_table
(
column_a
)
SELECT
column_b
FROM data_mart.dbo.source_table
WHERE
foo = 'bar';
当我在SQL Server Management Studio中执行查询时,这些运行正常。当我尝试使用EXEC load_stuff执行它们时,该过程失败并带有安全警告:
服务器主体“the_user”无法访问当前安全上下文下的数据库“data_mart”。
sproc的OWNER是dbo,它是the_user(为了我们的例子)。两个数据库的OWNER也是the_user,the_user映射到dbo(这是SQL Server应该做的)。
为什么我会在SQL Server中看到此错误?这是因为有问题的用户被别名为dbo而我应该使用不同的用户帐户进行跨数据库数据访问?
修改 我知道这是因为SQL Server默认禁用跨数据库所有权链接,这很好。但是,我不确定这种情况下的最佳做法。如果有人对此场景的最佳实践有任何意见,我们将不胜感激。
编辑2 最终的解决方案是在两个数据库上设置TRUSTWORTHY ON。这允许在两个数据库之间进行有限的所有权链接,而无需使用完整的数据库所有权链接。
答案 0 :(得分:2)
为什么不删除EXECUTE AS OWNER?
通常,执行SP的用户在两个数据库中都拥有适当的权限,而我根本不需要这样做。
答案 1 :(得分:1)
无需创建登录,您只需在目标数据库中启用访客用户。
授予与访客的连接
这允许执行用户在访客上下文下输入DB,并且当“db chaining为ON访问时不会在目标数据库中检查。
答案 2 :(得分:0)
实际上,DBO是一个角色(您可以将其视为一组用户),而不是自己的用户。 (除非您可以使用dbo连接到SQL SERVER:passwordfordbo,它不是用户)。
通常,在SQL Server的精彩世界中,如果授予userX权限执行storedprocY,那么即使X对Y中使用的所有对象都没有所有权限,X也有权执行Y包含的所有任务。 。
将业务逻辑封装在存储过程中是非常有用的功能。 (您的用户无法访问表,但他们可以执行一个存储过程。)
当我们谈论“所有权链接”时,它意味着以下(如果我错了,请纠正我) - 如果禁用所有权链接:只要所有必需对象都在同一个数据库中,执行procedureX的权限就会起作用 - 启用链接:“特权”将扩展到所有数据库。
希望有所帮助,