2010-09-28 48 views
32

我有一个SQL Server 2008数据库,通过存储过程完成对基础表的所有访问。有些存储过程只是从表中选择记录,而另一些则是UPDATE,INSERT和DELETE。存储过程和权限 - 是否EXECUTE足够?

如果一个存储过程更新一个表,执行存储过程的用户是否也需要对受影响的表的UPDATE权限,或者是他们对该存储过程具有足够EXECUTE权限的事实?

基本上我想知道如果给存储过程的用户EXECUTE权限是否足够或者我需要给他们SELECT,UPDATE,DELETE和INSERT权限的表,以便存储过程的工作。谢谢。

[编辑]在我的大多数存储过程中,确实看起来EXECUTE已经足够。但是,我发现在执行“执行sp_Executesql”的存储过程中,EXECUTE不够用。涉及的表需要具有“sp_Executesql”中正在执行的操作的权限。

+3

恐怕在使用动态SQL查询时,您需要授予底层对象的权限。我已经更新了答案以反映这一点。 – 2010-09-29 08:04:38

+0

@Noel - 你是对的。我发现我需要允许数据读取器访问用户的表格。谢天谢地,这不是我的情况,因为所有用户都被允许查看所有数据。 – webworm 2010-10-05 14:38:25

+0

在另一个答案中,@RemusRusanu链接到一个替代方案:1)创建一个证书; 2)创建与该证书关联的用户; 3)授予用户适当的权利[对受保护的资源];和4)用证书签名sproc,每次更改sproc(stackoverflow.com/a/4081604/6894566,链接到:sommarskog.se/grantperm.html#Certificates)。签名将证书用户权限添加到当前用户令牌,SQL Server在调用通过EXEC()或sp_executesql调用的系统过程和动态SQL时保留该权限。所以这个sproc成功了。 – iokevins 2017-08-08 21:11:40

回答

11

对存储过程执行权限就足够了。

CREATE TABLE dbo.Temp(n int) 

GO 
DENY INSERT ON dbo.Temp TO <your role> 
GO 
CREATE PROCEDURE dbo.SPTemp(@Int int) 
AS 

INSERT dbo.Temp 
SELECT @Int 

GO 

GRANT EXEC ON dbo.SPTemp TO <your role> 

GO 

然后(非的db_owner)用户将享有以下权利:

EXEC dbo.SPTemp 10 
GO 

INSERT dbo.Temp --INSERT permission was denied on the object 'Temp' 
SELECT 10 

但是,如果里面有dbo.SPTemp动态SQL试图插入dbo.Temp那么将失败。在这种情况下,需要授予对表的直接许可。

+7

这至少是误导性的,如果没有错的话。您的示例仅适用于此过程的所有者和表的所有者相同,并且所有权链接跳过访问检查。如果程序的拥有者不是该表的所有者,但只是拥有CONTROL权限(即拥有* all *权限,但不是所有者),则您的示例将失败。 – 2010-09-28 17:42:10

+1

@Remu,您需要成为db_owner角色的成员,以便您的方案通过。 – 2010-09-28 17:57:04

+0

在另一个答案中,@RemusRusanu链接到一个替代方案:1)创建一个证书; 2)创建与该证书关联的用户; 3)授予用户适当的权利[对受保护的资源];和4)在证书上签名sproc,每次更改sproc(https://stackoverflow.com/a/4081604/6894566,链接到:http://www.sommarskog.se/grantperm.html#Certificates) 。签名将证书用户权限添加到当前用户令牌,SQL Server在调用通过EXEC()或sp_executesql调用的系统过程和动态SQL时保留该权限。所以这个sproc成功了。 – iokevins 2017-08-07 21:25:52

23

如果表和proc拥有相同的所有者,则不会检查表的权限(包括DENY)。只要模式具有相同的所有者,它们也可以处于不同的模式中。

Ownership chaining MSDN上

编辑,从已删除的答案评论。

除非已使用EXECUTE AS,否则上下文总是当前登录:仅检查被引用的对象DML权限。在没有权限分配给可引用表单的存储过程中尝试OBJECT_ID(被引用表)。它给NULL。如果由存储过程的所有者执行,那么它会给出一个值,因为owener对可引用表有权限

+0

+1对于提及DENY – 2010-09-29 12:49:50

+0

'OBJECT_ID'提示非常有帮助;我需要一种方法来检查用户是否能够执行一个存储过程,这个工作非常漂亮 – Simon1979 2015-01-28 01:26:52

2

执行插入,更新或删除的存储过程的执行权限就足够了。您不需要在表级别授予这些权限。事实上,我会劝阻这种方法。使用存储过程可以更好地控制更改的发生。例如,您可能希望在允许更新之前进行一些检查。使用存储过程还可以帮助防止重大事故 - 例如删除表中的所有行,因为有人忘记了WHERE子句!

0

非常感谢!我有类似的问题。这导致我的答案。

我试图在存储过程中调用一个表,调用嵌套在IF语句中的其他存储过程。

我的错误是

服务器主体“域\添加my_id”不能在当前安全上下文下访问数据库“2nd_DB”。

我给调用存储过程的权限做截断(EXECUTE AS SELF),然后造成了问题,因为SELF没有权利对第二个DB。我们的解决方案是将截断移到另一个SP,包括EXECUTE AS SELF。我们现在称之为truncate SP,执行我们的数据处理,进行逻辑判断,然后调用适当的第三个SP。

1

也许你可以使用

“以执行为业主” 当你创建存储procedure.such如下

create procedure XXX 
with execute as owner 
as 
begin 
... 
end 
go 

那么你只需要授予用户存储过程XXX的执行权限。

+0

这为我工作。希望通过存储过程为用户提供对表的访问权限,并且这一工作成功。该表不必由存储过程拥有相同的模式。 – gopstar 2017-12-12 14:37:29