如果表和过程具有相同的所有者,则不会检查表的权限。这称为所有权链接。
请注意,此上下文中的“所有权”是指“模式所有者”。例如,该表TestDB.Schema1.Table1
由拥有 的用户拥有Schema1
。
因为Orders
具有相同的所有者GetCustomerOrderInfo
,存储过程具有读取的隐式权限Orders
。
但是Customers
拥有不同的所有者,因此您必须明确授予权限。
这是一个演示该问题的测试脚本:
use Test
go
if exists (select * from sys.syslogins where name = 'UserA')
drop login UserA
create login UserA with password = 'Welcome'
if exists (select * from sys.syslogins where name = 'UserB')
drop login UserB
create login UserB with password = 'Welcome'
if exists (select * from sys.syslogins where name = 'UserC')
drop login UserC
create login UserC with password = 'Welcome'
if exists (select * from sys.tables where name = 'Customers' and schema_name(schema_id) = 'SchemaA')
drop table SchemaA.Customers
if exists (select * from sys.schemas where name = 'SchemaA')
drop schema SchemaA
if exists (select * from sys.sysusers where name = 'UserA')
drop user UserA
if exists (select * from sys.tables where name = 'Orders' and schema_name(schema_id) = 'SchemaB')
drop table SchemaB.Orders
if exists (select * from sys.procedures where name = 'GetCustomerOrderInfo' and schema_name(schema_id) = 'SchemaB')
drop procedure SchemaB.GetCustomerOrderInfo
if exists (select * from sys.schemas where name = 'SchemaB')
drop schema SchemaB
if exists (select * from sys.sysusers where name = 'UserB')
drop user UserB
if exists (select * from sys.sysusers where name = 'UserC')
drop user UserC
create user UserA for login UserA
alter role db_owner add member UserA
go
create schema SchemaA authorization UserA
go
create user UserB for login UserB
alter role db_owner add member UserB
go
create schema SchemaB authorization UserB
go
create user UserC for login UserC
create table SchemaA.Customers (id int identity)
create table SchemaB.Orders (id int identity, CustomerId int)
go
create procedure SchemaB.GetCustomerOrderInfo
as
select *
from SchemaB.Orders o
join SchemaA.Customers c
on c.id = o.CustomerId
go
当我们都设置好后,我们可以使用不同的权限测试该过程。首先,我们需要对存储过程具有执行权限,然后对Customers
. 之后,存储过程就可以工作了,即使我们没有授予Orders
.
execute as login = 'UserC' -- Login as UserC
exec SchemaB.GetCustomerOrderInfo
-- The EXECUTE permission was denied on the object 'GetCustomerOrderInfo', database 'Test', schema 'SchemaB'
revert -- Revert back to our original login
grant execute on SchemaB.GetCustomerOrderInfo to UserC
execute as login = 'UserC'
exec SchemaB.GetCustomerOrderInfo
-- The SELECT permission was denied on the object 'Customers', database 'Test', schema 'SchemaA'.
revert
grant select on SchemaA.Customers to UserC
execute as login = 'UserC'
exec SchemaB.GetCustomerOrderInfo
-- (0 row(s) affected)
revert