admin

存储过程和基础表上的SQL Server用户权限

sql

下面的正确答案是什么?我本以为EXECUTE许可就足够了?谢谢!

该数据库具有一个名为Customersowned by的表UserA和另一个名为Ordersowned
by的表UserB。你也有一个存储过程GetCustomerOrderInfoUserBGetCustomerOrderInfo从两个表中选择数据。您创建一个新用户UserC。您需要确保UserC可以调用该GetCustomerOrderInfo存储过程。您还只需要分配最低要求的权限即可UserC


阅读 173

收藏
2021-06-07

共1个答案

admin

如果表和过程的所有者相同,则不检查表的权限。这称为所有权链接

注意,在此上下文中,“所有权”是指“模式所有者”。例如,该表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
2021-06-07