授予对存储过程、函数和视图的执行权限

Jac*_*all 6 sql-server-2008 stored-procedures permissions functions

我正在使用仅具有读取权限的用户。它基本上有权限

  • 连接
  • 执行

但是,它没有对函数和存储过程的执行权限。在我的部分报告中,我调用了我自己的函数。我想readonlyuser授予执行 SP、函数和视图的权限。

我遇到了 这段代码,它显示了如何为特定用户授予对存储过程和函数的执行权限。

- Grant Execute on all functions for testuser
declare @username varchar(255)  
set @username = 'testuser'  
SELECT 'grant exec on ' + QUOTENAME(ROUTINE_SCHEMA) + '.' +  
QUOTENAME(ROUTINE_NAME) + ' TO ' + @username FROM INFORMATION_SCHEMA.ROUTINES  
WHERE OBJECTPROPERTY(OBJECT_ID(ROUTINE_NAME),'IsMSShipped') = 0   
and ROUTINE_TYPE='PROCEDURE'  
Run Code Online (Sandbox Code Playgroud)

和函数

declare @username varchar(255)  
set @username = 'testuser'  
SELECT 'grant exec on ' + QUOTENAME(ROUTINE_SCHEMA) + '.' +  
QUOTENAME(ROUTINE_NAME) + ' TO ' + @username FROM INFORMATION_SCHEMA.ROUTINES  
WHERE OBJECTPROPERTY(OBJECT_ID(ROUTINE_NAME),'IsMSShipped') = 0   
and ROUTINE_TYPE='FUNCTION'  
Run Code Online (Sandbox Code Playgroud)

现在,这里看起来此权限仅适用于现有 SP 和功能。如果添加新函数,则必须再次运行此代码以授予权限。

问题

  1. 如果我上面的解释没有错,有没有办法给只读用户授予执行权限,以便您对所有函数和存储过程都有权限,即使您创建新函数?

  2. 我可以对视图应用相同的权限吗?

  3. 此线程中,据说您不能对返回表的函数授予执行权限。真的吗?

我知道有几个问题,但它们都是相关的。最好在一个地方。

Aar*_*and 9

确实,您不能授予EXEC对返回表的函数的权限。这种类型的函数实际上更像是一个视图而不是一个函数。您需要改为授予 SELECT ,例如:

GRANT SELECT ON dbo.Table_Valued_Function TO [testuser];
Run Code Online (Sandbox Code Playgroud)

所以你的脚本看起来更像这样(对不起,但我绝对讨厌INFORMATION_SCHEMA并且更喜欢使用目录视图,它也不需要像这样的函数OBJECTPROPERTY):

DECLARE 
    @sql      NVARCHAR(MAX) = N'',
    @username VARCHAR(255)  = 'testuser';

SELECT @sql += CHAR(13) + CHAR(10) + N'GRANT ' + CASE 
    WHEN type_desc LIKE 'SQL_%TABLE_VALUED_FUNCTION'
      OR type_desc = 'VIEW'
    THEN ' SELECT ' ELSE ' EXEC ' END 
    + ' ON ' + QUOTENAME(SCHEMA_NAME([schema_id])) 
    + '.' + QUOTENAME(name) 
    + ' TO ' + @username + ';'
 FROM sys.all_objects
WHERE is_ms_shipped = 0 AND
( 
    type_desc LIKE '%PROCEDURE' 
    OR type_desc LIKE '%FUNCTION'
    OR type_desc = 'VIEW'
);

PRINT @sql;
-- EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

现在您可以授予EXEC架构,并始终在该架构中创建这些过程(实际上是架构的目的之一!),@jgardner04 已经建议,但是为了使此解决方案也适用于表值函数,您倒也得准SELECT。如果您没有在该模式中的表中存储任何数据(或者至少您想隐藏它们),这没关系,但它也适用于任何表和视图,这可能不是您的意图。

另一个想法(例如,如果您不能或不想使用模式)是编写一个 DDL 触发器来捕获CREATE_PROCEDURE,CREATE_FUNCTIONCREATE_VIEW事件,并向用户(或一组用户,如果您想将它们存储在表中):

CREATE TRIGGER ApplyPermissionsToAllProceduressAndFunctions -- be more creative!
    ON DATABASE FOR CREATE_PROCEDURE, CREATE_FUNCTION, CREATE_VIEW
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE
        @sql       NVARCHAR(MAX),
        @EventData XML = EVENTDATA();

    ;WITH x ( sch, obj ) 
    AS
    (
        SELECT
          @EventData.value('(/EVENT_INSTANCE/SchemaName)[1]',  'NVARCHAR(255)'), 
          @EventData.value('(/EVENT_INSTANCE/ObjectName)[1]',  'NVARCHAR(255)')
    )
    SELECT @sql = N'GRANT ' + CASE 
      WHEN o.type_desc LIKE 'SQL_%TABLE_VALUED_FUNCTION' 
        OR o.type_desc = 'VIEW'
      THEN ' SELECT ' 
      ELSE ' EXEC ' END 
        + ' ON ' + QUOTENAME(x.sch) 
        + '.' + QUOTENAME(x.obj) 
        + ' TO testuser;' -- hard-code this, use a variable, or store in a table
    FROM x
    INNER JOIN sys.objects AS o
    ON o.[object_id] = OBJECT_ID(QUOTENAME(x.sch) + '.' + QUOTENAME(x.obj));

    EXEC sp_executesql @sql;
END
GO
Run Code Online (Sandbox Code Playgroud)

我发现 DDL 触发器的缺点是您很快就会忘记它们的存在。因此,当您决定停止向所有新对象授予这些权限的一年后,可能需要一段时间来解决为什么它仍然会发生。在我的上一份工作中,我们将 DDL 触发器调用的所有操作记录到各种中央“事件日志”中,这是我们跟踪服务器上发生的似乎没有人记得的任何操作的首选位置(这是一个DDL 触发大约一半的时间)。所以你可以考虑添加一些额外的逻辑来帮助解决这个问题。

编辑

添加基于模式的代码,我将再次提到这将授予对在 foo 模式中创建的任何过程、函数表的权限。

CREATE SCHEMA foo;
GRANT EXEC, SELECT ON SCHEMA::foo TO testuser;
Run Code Online (Sandbox Code Playgroud)

现在,如果您创建以下过程,则 testuser 将能够执行:

CREATE PROCEDURE foo.proc1
AS 
BEGIN
    SET NOCOUNT ON;
    SELECT 1;
END
GO
Run Code Online (Sandbox Code Playgroud)


jga*_*r04 3

您能否利用架构,然后向用户授予执行架构中项目的权限?有关架构的更多信息可以在这里找到:http ://msdn.microsoft.com/en-us/library/ms187940.aspx