如何参数化SQL REVOKE命令

时间:2017-01-18 09:57:57

标签: asp.net sql-server sqldatasource

如何参数化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.`

我是否需要使用动态SQL来解决这个问题,还是有其他办法?

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

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

1 个答案:

答案 0 :(得分:1)

由于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