如何参数化 SQL REVOKE 命令

How to parameterise a SQL REVOKE command

如何参数化 SQL REVOKE 命令?

DECLARE @ViewName nvarchar = 'MyViewName'
DECLARE @UserRole nvarchar = 'MyRoleName'

REVOKE SELECT ON [@ViewName] TO [@UserRole]

输出以下错误:

Cannot find the object '@ViewName', because it does not exist or you do not have permission.`

我需要使用 Dynamic SQL 来解决这个问题还是有其他方法?

我的实际用例在 ASP.NET SqlDataClient 中并且正在生成代码,所以我对它的控制有限。发送到 SQL 的代码(由 SQL Profiler 嗅探)是:

exec sp_executesql N'REVOKE SELECT ON [@ViewName] TO [@UserRole]',N'@ViewName nvarchar(24),@UserRole nvarchar(12)',@ViewName=N'MyViewName',@UserRole=N'MyUserRole'

因为 GRANTREVOKE 本身需要相当大的权限,所以在构建动态 SQL 并且可以在不同的凭据下执行命令的存储过程中执行此操作通常很有吸引力.通过这种方式,您可以通过控制对存储过程的访问来选择性地将权限分配给 REVOKE,如果这成为一个要求,则添加审计,最后但并非最不重要的是,您可以继续使用参数。

在这种情况下:

CREATE PROCEDURE dbo.RevokeSelect(@ObjectName NVARCHAR(128), @RoleName NVARCHAR(128)) 
WITH EXECUTE AS OWNER AS BEGIN
    SET NOCOUNT ON;

    DECLARE @SQL NVARCHAR(MAX);
    SELECT @SQL = REPLACE(REPLACE(
        N'REVOKE SELECT ON @ObjectName TO @RoleName;',
        '@ObjectName', QUOTENAME(@ObjectName)),
        '@RoleName', QUOTENAME(@RoleName))
    ;
    -- For debugging
    --PRINT @SQL
    EXEC (@SQL)
END;
GO
GRANT EXECUTE ON dbo.RevokeSelect TO [application_login];

感谢 EXECUTE AS OWNER[application_login] 帐户不需要额外的权限;它可以通过存储过程对数据库中的任何对象进行REVOKE SELECT。这可能正是您想要的,但如果不是,您应该删除 EXECUTE AS OWNER 并授予个人 CONTROL 对对象的权限(但这当然也允许许多其他操作)。

请注意,执行动态 SQL 的过程需要仔细检查以确保它不易受到 SQL 注入的影响,就像使用动态 SQL 的任何其他过程一样。显然,如果过程使用 EXECUTE AS OWNER,这就更重要了,因为它可以做任何事情。在这种情况下,将 QUOTENAME 应用于两个参数就可以解决这个问题。

最后但同样重要的是,虽然EXECUTE AS OWNER简单方便,但如果数据库所有者不是一个帐户而是一个组,它将失败。在这种情况下,如果您想委派权限,则必须创建一个代理帐户以在 EXECUTE AS 中使用或使用证书对存储过程进行签名。如果开发人员不相信 EXECUTE AS OWNER 的强大功能,您可能仍想这样做。这超出了这个答案的范围,但是 Erland Sommerskog 在这个话题上有一个excellent writeup