如何参数化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'
答案 0 :(得分:1)
由于GRANT
和REVOKE
本身需要相当多的权限,因此在构建动态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。