存储过程和权限 - EXECUTE 是不是足够?

Posted

技术标签:

【中文标题】存储过程和权限 - EXECUTE 是不是足够?【英文标题】:Stored Procedure and Permissions - Is EXECUTE enough?存储过程和权限 - EXECUTE 是否足够? 【发布时间】:2011-04-18 10:36:44 【问题描述】:

我有一个 SQL Server 2008 数据库,其中对基础表的所有访问都是通过存储过程完成的。一些存储过程只是从表中选择记录,而其他存储过程则更新、插入和删除。

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

基本上,我想知道授予用户对存储过程的 EXECUTE 权限是否足够,或者我是否需要授予他们对表的 SELECT、UPDATE、DELETE 和 INSERT 权限才能使存储过程正常工作。谢谢。

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

【问题讨论】:

恐怕在使用动态 SQL 查询时,您需要授予对底层对象的权限。我已经更新了答案以反映这一点。 @Noel - 你是对的。我发现我需要允许 datareader 访问用户的表。值得庆幸的是,这对我来说不是问题,因为所有用户都可以查看所有数据。 在另一个答案中,@RemusRusanu 链接到一个替代方案:1)创建证书; 2)创建与该证书关联的用户; 3) 授予用户适当的权利[对受保护的资源];和 4) 每次更改 sproc (***.com/a/4081604/6894566, 链接到: sommarskog.se/grantperm.html#Certificates ) 时使用证书对 sproc 进行签名。签名将证书用户权限添加到当前用户令牌中,SQL Server 在调用系统过程和通过 EXEC() 或 sp_executesql 调用的动态 SQL 时保留该权限。所以存储过程成功了。 【参考方案1】:

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

请参阅 MSDN 上的 Ownership chaining

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

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

【讨论】:

OBJECT_ID 提示很有帮助;我需要一种方法来检查用户是否能够执行存储过程,这很好用【参考方案2】:

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

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 中,则会失败。在这种情况下,需要授予对表的直接权限。

【讨论】:

这至少是误导,如果不是错误的话。您的示例之所以有效,是因为过程的所有者和表的所有者相同,并且所有权链接跳过了访问检查。如果过程的所有者不是是表的所有者,而只是对它具有 CONTROL 权限(即具有 all 权限,但不是所有者),你的例子会失败。 @Remu,您需要成为 db_owner 角色的成员才能通过您的场景。 在另一个答案中,@RemusRusanu 链接到一个替代方案:1)创建证书; 2)创建与该证书关联的用户; 3) 授予用户适当的权利[对受保护的资源];和 4) 每次更改 sproc (***.com/a/4081604/6894566, 链接到:sommarskog.se/grantperm.html#Certificates) 时,使用证书对 sproc 进行签名。签名将证书用户权限添加到当前用户令牌中,SQL Server 在调用系统过程和通过 EXEC() 或 sp_executesql 调用的动态 SQL 时保留该权限。所以sproc成功了。【参考方案3】:

也许你可以使用

“以所有者身份执行”

当你创建存储过程时,如下所示:

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

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

【讨论】:

这对我有用。正在寻求仅通过存储过程向用户提供对表的访问,这很有效。该表不必与存储过程属于同一架构。 (搜索词)sp_executesql Azure SQL Server 动态 sql 对 Sql Azure 上的动态 sql 的特殊权限(结束关键字)。这似乎在 Azure SQL 上以一种非常柔和的方式出错。您在 SQL Azure 中经常有不同的用户上下文,而这个细节正是您要寻找的。​​span> 【参考方案4】:

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

【讨论】:

在这种情况下,您需要查看上面的刘元的答案才能实现您所说的目标。【参考方案5】:

非常感谢!我有一个类似的问题。这让我找到了答案。

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

我的错误是

服务器主体“domain\my_id”在当前安全上下文下无法访问数据库“2nd_DB”。

我已授予调用存储过程的权限以执行截断 (EXECUTE AS SELF),这导致了一个问题,因为 SELF 没有对第二个 DB 的权限。我们的解决方案是将截断移动到另一个 SP,包括 EXECUTE AS SELF。我们现在调用 truncate SP,执行我们的数据处理,进行逻辑判断,然后调用适当的 3rd SP。

【讨论】:

以上是关于存储过程和权限 - EXECUTE 是不是足够?的主要内容,如果未能解决你的问题,请参考以下文章

存储过程权限和执行

mysql 存储过程执行异常,参数不是出参

GRANT EXECUTE 对所有存储过程

mysql存储过程

sqlserver 存储过程 使用事务,说明在下边,求大神指教!

MySQL 存储过程-definer和invoker的解释