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

标签 sql sql-server

以下问题的正确答案是什么?我会认为 EXECUTE 权限就足够了?? 谢谢!

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

分配所需的最低权限

最佳答案

如果表和过程具有相同的所有者,则不会检查表的权限。这叫做 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

关于SQL Server 用户对存储过程和基础表的权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19517251/

相关文章:

php - 从具有相同结构的不同表中获取结果

sql - 在 where 子句中使用小数 - 将 nvarchar 转换为数字数据类型时出现算术溢出错误

mysql - 所有数据库表中 CreatedDate 和 ModifiedDate 列的优缺点

c# - 在C#中如何确定SQL Server数据库列是否自动增量?

sql - NOT IN with Nulls - 不明确的行为

php - 从 Table1 中选择一个随机行,其中 id 在 Table2 中不存在

mysql - 选择以特定字符结尾的所有值

列出 future 和过去 14 天内所有生日的 SQL

java - 如何解决 SQLServerException : Invalid object name?

sql - 向现有列添加标识