SQL Server 2016中EXECUTE AS SELF与跨数据库视图的权限异常问题
为啥会出现这个问题?
当你用EXECUTE AS SELF创建存储过程dbo.f时,这个存储过程会以创建它的你的身份来执行。虽然你直接查询TheView没问题,但这里的核心坑在于:SQL Server默认不允许跨数据库的权限链自动传递——哪怕你是B库的dbo,在A库的存储过程上下文里访问B库的表时,权限校验会因为跨库上下文的切换而失败,导致你看到的权限不足类错误。
解决办法来啦(按安全优先级排序)
1. 开启跨库所有权链(最推荐)
如果TheView(A库的dbo所有)和SomeTable(B库的dbo所有)的所有者一致(都是dbo),你可以给两个数据库开启DB_CHAINING属性,这样跨库的所有权链就能生效,存储过程执行时就不会卡在权限校验上了:
-- 给数据库A开启跨库所有权链 ALTER DATABASE A SET DB_CHAINING ON; GO -- 给数据库B开启跨库所有权链 ALTER DATABASE B SET DB_CHAINING ON; GO
执行完这两句后,再运行dbo.f应该就能正常返回结果了。
2. 把EXECUTE AS改成OWNER
如果你的存储过程所有者是A库的dbo,且这个dbo对应的登录账号在B库也拥有dbo权限,那可以把存储过程的执行上下文换成OWNER:
USE A; GO ALTER PROC dbo.f WITH EXECUTE AS OWNER AS SELECT * FROM TheView; GO
EXECUTE AS OWNER会以存储过程所有者的身份执行,跨库访问同所有者的对象时,权限传递会更顺畅。
3. 谨慎开启TRUSTWORTHY(不推荐,有安全风险)
如果上面两种方法都不适用,你可以尝试开启A库的TRUSTWORTHY属性,但必须注意:这会让A库的所有者获得服务器级别的权限,存在不小的安全隐患,非必要情况下不建议使用:
ALTER DATABASE A SET TRUSTWORTHY ON; GO
内容的提问来源于stack exchange,提问作者Seva Alekseyev




