0

我读过一篇文章

http://www.sommarskog.se/grantperm.html#ownershipchaining

其中有关于 SQL Server 中所有权链接的非常好的信息。

这就是我在 SQL Server 2008 上所做的,

  1. 使用登录 sa 创建了 2 个数据库 DatabaseA、DatabaseB
  2. 在 DatabaseA 中创建了一个过程“TestProc”,该过程在 DatabaseB 中执行了一个过程
  3. 创建了一个登录'testuser'
  4. 在 DatabaseA 中将此登录添加为用户并授予执行过程“TestProc”的权限

正如你所看到的,我的目标是让“testuser”在 DatabaseB 中执行一个过程,而不在 DatabaseB 中添加这个用户,也不给他对 DatabaseB 中过程的直接执行权限。

我确实在服务器级别和两个数据库上启用了所有权链接。我已经重新启动了 SQL Server 服务。

但仍然收到此错误

消息 916,级别 14,状态 1,过程 TestProc,第 18 行 服务器主体“testuser”无法在当前安全上下文下访问数据库“DatabaseB”。

我在这里错过了什么吗?

4

1 回答 1

0

所有权链接适用于数据库内的对象。它不允许您输入数据库本身。因此,您必须在您读取的任何数据库中创建一个登录名,例如:

use DatabaseB
exec sp_grantdbaccess 'testuser'

所有权链接确实授予对存储过程的权限。所以数据库登录可以没有任何权限。它必须存在。

创建两个测试数据库并在一个中调用一个过程的查询:

use master
if exists (select * from sys.databases where name = 'TestDatabase1')
    drop database TestDatabase1
if exists (select * from sys.databases where name = 'TestDatabase2')
    drop database TestDatabase2
create database TestDatabase1
go
use TestDatabase1
exec sp_changedbowner 'sa'
go
create procedure dbo.sp1 as select 'hello world!'
go
create database TestDatabase2
go
use TestDatabase2
exec sp_changedbowner 'sa'
go
create procedure dbo.sp2 as exec TestDatabase1.dbo.sp1
go
use TestDatabase2
exec sp_grantdbaccess 'testuser'
grant execute on sp2 to testuser as dbo
use TestDatabase1
-- Either of the below lines would work
-- exec sp_grantdbaccess 'guest'
-- exec sp_grantdbaccess 'testuser'
use TestDatabase2
execute as login = 'testuser'
exec sp2
revert -- Revert back to original login

查询以显示数据库和过程的所有权:

select  d.name
,       l.name
from    sys.databases d
join    sys.syslogins l
on      d.owner_sid = l.sid
where   d.name like '...your database...'

select  p.name
,       dp.name
from    TestDatabase.sys.procedures p
join    TestDatabase.sys.schemas s
on      s.schema_id = p.schema_id
join    TestDatabase.sys.database_principals dp
on      s.principal_id = dp.principal_id
where   p.name like '...your stored procedure...'
于 2011-12-28T18:37:11.130 回答