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

时间:2013-10-22 11:59:39

标签: sql sql-server

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

数据库有Customers拥有的UserA表和Orders拥有的另一个名为UserB的表。您还拥有GetCustomerOrderInfo拥有的存储过程UserBGetCustomerOrderInfo从两个表中选择数据。您创建了一个新用户UserC。您需要确保UserC可以调用GetCustomerOrderInfo存储过程。您还需要仅为UserC

分配所需的最低权限

2 个答案:

答案 0 :(得分:8)

如果表和过程具有相同的所有者,则不会检查表的权限。这称为ownership chaining

请注意,此上下文中的“所有权”表示“架构所有者”。例如,表TestDB.Schema1.Table1归拥有Schema1的用户所有。

由于OrdersGetCustomerOrderInfo具有相同的所有者,因此存储过程具有从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

答案 1 :(得分:0)

如上所述,SP的架构所有者和基础对象应相同。 通过以下方式检查架构所有者:

 "message": "221.251.246.139 - - [14/Sep/2020:04:56:04 +0000] \"POST /services/api/agent/liveview_image_upload HTTP/1.1\" 200 45 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko\" 6019 234 1618 \"-\""

要更改架构的所有者,您可以:

%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})) %{NUMBER:response} (?:%{NUMBER:bytes})

示例:

select name, USER_NAME(s.principal_id) AS Schema_Owner from sys.schemas s

最后,如果在SP中要截断表或更改结构,则可能要在SP中添加WITH EXECUTE AS OWNER:

ALTER AUTHORIZATION ON SCHEMA::YOUR_SCHEMA TO YOUR_USER;