Asp.net 如何参数化SQL REVOKE命令

Asp.net 如何参数化SQL REVOKE命令,asp.net,sql-server,sqldatasource,Asp.net,Sql Server,Sqldatasource,如何参数化SQLREVOKE命令 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
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探查器嗅探)的代码是:


由于
GRANT
REVOKE
本身需要相当大的权限,因此在构建动态SQL并可以在不同凭据下执行命令的存储过程中执行此操作通常很有吸引力。这样,您可以通过控制对存储过程的访问来有选择地分配
撤销
的权限,如果这成为一项要求,可以添加审核,最后但并非最不重要的是,您可以继续使用参数

在这种情况下:

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];
由于
以所有者身份执行
[应用程序登录]
帐户不需要额外的权限;它可以通过存储过程对数据库中的任何对象执行
REVOKE SELECT
。这可能正是您想要的,但如果不是,您应该删除
executeasowner
,并对对象授予单独的
CONTROL
权限(当然,这也允许许多其他操作)

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


最后但并非最不重要的一点是,虽然
以所有者身份执行
简单方便,但如果数据库所有者不是帐户而是组,则它将失败。在这种情况下,如果要委派权限,则必须创建一个代理帐户,以便在
执行为
中使用,或者使用证书对存储过程进行签名。如果开发者不能信任
executeasowner
的强大功能,您可能还是希望这样做。这超出了本回答的范围,但Erland Sommerskog对此有一个明确的定义。

您必须使用动态sql。因为
GRANT
REVOKE
本身需要相当大的权限,在构建动态SQL并可以在不同凭据下执行命令的存储过程中这样做通常很有吸引力。这样,您就可以通过控制对存储过程的访问,有选择地分配
撤销
的权限,如果需要添加审核,最后但并非最不重要的一点是,您可以继续使用参数。@jeroenmoster这听起来是正确的答案。如果你把它作为一个答案,并添加一个小的例子,那么我会标记它是正确的。感谢你花时间将你的评论扩展成完整的答案。杰出的是否也可以参数化
选择
?i、 e.
撤销@ObjectName对@RoleName的@Permission
。当我尝试这样做时,我在“选择”附近得到一个错误错误语法。我试图从一个SqlDataSource执行,该SqlDataSource生成以下SQL(由SQL事件探查器捕获):
exec revokeRolePermission@Permission=N'SELECT'、@RoleName=N'MyRoleName'、@ObjectName=N'MyViewName'
@Adam:您可以使用文本替换,就像使用其他两个参数一样。添加另一个
REPLACE(
。注意,这样做还允许像
REVOKE BANANA
这样的无意义调用;如果这是一个问题,您可能希望存储过程只检查参数(
如果@Permission='SELECT',那么…
)。@Adam:确保检查参数(
如果@Permission不在('SELECT','GRANT'))BEGIN;RAISERROR(…);RETURN;
)因为您打开了SQL注入的大门,使用这个无法转义的新字符串(例如,
@Permission=N'REVOKE ALL ON X to dbo;DROP TABLE myimportantable;--
“将很乐意构造一个非常糟糕的语句)虽然在编写应用程序时可能不会发生这种情况,但在存储过程中完全阻止它仍然是一个很好的做法。更好的是,考虑到这两个单独的过程,因为要做的事情非常有限。对于 Grime,当然可以阅读其他内容(您不能<代码> RevoCKEGE/<代码>)。。如果我们谈论的是视图,很难理解为什么您需要授予或撤销除
选择
权限以外的任何其他权限。如果您要将此扩展到其他对象和权限,请注意不要意外创建一个安全噩梦,可以授予任何人任何权限,因为这很容易被利用。(显然,撤销的风险要小一些。)在所有情况下,预防注射都是必要的。
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];