2017-01-18 3 views
0

Как я могу параметризовать команду SQL REVOKE?Как параметризовать команду 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 Profiler) является:

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

Вы должны использовать динамический sql. –

+0

Поскольку 'GRANT' и' REVOKE' сами требуют значительных разрешений, обычно это делается в хранимой процедуре, которая создает динамический SQL и может выполнять команды под разными учетными данными. Таким образом, вы можете выборочно назначать право на «REVOKE», контролируя доступ к хранимой процедуре, добавляя аудит, если это когда-либо станет требованием, и, наконец, не в последнюю очередь вы можете продолжать использовать параметры. –

+0

@JeroenMostert, который звучит как правильный ответ. Если вы поместите это как ответ и добавьте небольшой пример, я помечаю его правильно. – Adam

ответ

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. Это выходит за рамки этого ответа, но у Эрланда Соммерскога есть excellent writeup по этой теме.

+0

Благодарим вас за то, что нашли время, чтобы развернуть свой комментарий в полный ответ. Отлично! – Adam

+0

Можно ли параметризовать 'SELECT'? то есть 'REVOKE @Permission ON @ObjectName TO @ RoleName'. Когда я пытаюсь сделать это, я получаю неправильный синтаксис ошибки рядом с «SELECT» *.Я пытаюсь выполнить из SqlDataSource, который генерирует следующий SQL (захвачен SQL Profiler): 'exec revokeRolePermission @ Permission = N'SELECT ', @ RoleName = N'MyRoleName', @ ObjectName = N'MyViewName'' – Adam

+0

@ Адам: Вы можете использовать текстовую замену, как это было сделано с двумя другими параметрами. Добавьте еще один 'REPLACE ('. Заметьте, что для этого также допускаются бессмысленные вызовы типа REVOKE BANANA, если это проблема, вы можете захотеть, чтобы хранимая процедура просто проверила аргументы ('IF @Permission = 'SELECT' THEN ... '). –