Give permissions to a stored procedure

自古美人都是妖i 提交于 2019-12-11 19:37:26

问题


I have a stored procedure that does a merge into a table. Let's call it someSchema.UpsertSomeStuff (note that it is not in the dbo schema). Let's call the table dbo.SomeStuff (note that it is in the dbo schema).

When I call the stored procedure with a data reader/data writer user, it works fine.

But if I give permissions to call this stored procedure to a very weak user (no data writer or reader rights), then it fails telling me that I can't select, insert or update to dbo.SomeStuff.

I don't want to give this weak user access to that table. I just want the stored procedure to have access.

I tried using WITH EXECUTE AS OWNER and it seemed to work, but then my co-worker started getting this error when he tried to modify the stored procedures:

Cannot execute as the user 'MyUserNameHere', because it does not exist or you do not have permission.

I am a bit confused about the difference between the owner and the schema. But I think there should be a way to get this done with out having to tie it to my personal user account.


回答1:


What you need is to sign the procedure.

Let me borrow the setup from the link M.Ali provided in his comment (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

This was the setup, thx to Andomar.

We can give the UserC execute permission on the procedure:

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

This wasn't good enough. What we can do is create a certificate in the database, a database user on this certificate, give that user appropriate permissions (db_owner role in this sample), and then sign the procedure with the certificate:

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

It should work OK now.

Points to make: the user created on the certificate cannot be used as a normal user, there is no login with it and it's not a security problem; all the permissions we give that user will be added to context in which the procedure is executed when we add a signature; If we alter the procedure, we have to sign it again.



来源:https://stackoverflow.com/questions/22796785/give-permissions-to-a-stored-procedure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!