我有一个存储过程可以合并到表中。我们称之为someSchema.UpsertSomeStuff
(请注意,它不在dbo
架构中)。让我们调用表dbo.SomeStuff
(注意它在dbo
模式中)。
当我使用数据读取器/数据写入器用户调用存储过程时,它可以正常工作。
但是,如果我授予权限以将此存储过程调用给非常弱的用户(没有数据写入者或读者权限),则它无法告诉我无法选择,插入或更新到dbo。SomeStuff
我不想让这个弱用户访问该表。我只是希望存储过程能够访问。
我尝试使用WITH EXECUTE AS OWNER
它似乎有效,但是当我试图修改存储过程时,我的同事开始收到此错误:
无法以“MyUserNameHere”用户身份执行,因为它不存在或您没有权限。
我对所有者和架构之间的区别感到有点困惑。但我认为应该有办法完成这项工作,而不必将其与我的个人用户帐户联系起来。
答案 0 :(得分:0)
您需要签署该程序。
让我借用M.Ali在评论中提供的链接(SQL Server User Permissions on Stored Procedure and Underlying Tables):
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
这是Andomar的设置。
我们可以为程序提供UserC执行权限:
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
这还不够好。我们可以做的是在数据库中创建证书,该证书上的数据库用户,为该用户授予适当的权限(此示例中为db_owner角色),然后使用证书对该过程进行签名:
create certificate cert_raiser
encryption by password = 'pGFD4bb925DGvbd2439587y'
with subject = 'raiser',
expiry_date = '01/01/2114';
go
create user cert_user from certificate cert_raiser
go
alter role db_owner add member cert_user
go
add signature to SchemaB.GetCustomerOrderInfo
by certificate cert_raiser
with password = 'pGFD4bb925DGvbd2439587y';
go
现在应该可行了。
要点:在证书上创建的用户不能用作普通用户,没有登录,也不是安全问题;我们为该用户提供的所有权限都将添加到我们添加签名时执行该过程的上下文中;如果我们改变程序,我们必须再次签名。