Encrypt the stored procedure created by SqlDependency
I created a SqlDependency so that an event would fire when the results of a particular query change.
// Create a command
SqlConnection conn = new SqlConnection(connectionString);
string query = "SELECT MyColumn FROM MyTable;";
SqlCommand cmd = new SqlCommand(query, conn)
cmd.CommandType = CommandType.Text;
// Register a dependency
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += DependencyOnChange;
When this code executes, a stored procedure is automatically created with a name like
SqlQueryNotificationStoredProcedure-82ae1b92-21c5-46ae-a2a1-511c4f849f76
This procedure is unencrypted, which violates requirements I have been given. I have two options:
How can I accomplish option 2?
Contents of the stored procedure in question:
CREATE PROCEDURE [dbo].[SqlQueryNotificationStoredProcedure-b124707b-23fc-4002-aac3-4d52a71c5d6b]
AS
BEGIN
BEGIN TRANSACTION;
RECEIVE TOP (0) conversation_handle
FROM [SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b];
IF (
SELECT COUNT(*)
FROM [SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b]
WHERE message_type_name = 'http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer'
) > 0
BEGIN
IF (
(
SELECT COUNT(*)
FROM sys.services
WHERE NAME = 'SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b'
) > 0
)
DROP SERVICE [SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b];
IF (OBJECT_ID('SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b', 'SQ') IS NOT NULL)
DROP QUEUE [SqlQueryNotificationService-b124707b-23fc-4002-aac3-4d52a71c5d6b];
DROP PROCEDURE [SqlQueryNotificationStoredProcedure-b124707b-23fc-4002-aac3-4d52a71c5d6b];
END
COMMIT TRANSACTION;
END
GO
Create a DDL trigger that checks if a procedure with a name like "SqlQueryNotificationStoredProcedure-" is being created, and if so, immediately alter it WITH ENCRYPTION
instead:
CREATE TRIGGER [TR_EncryptQueryNotificationProcedures]
ON DATABASE
AFTER CREATE_PROCEDURE, ALTER_PROCEDURE
AS
BEGIN
SET ARITHABORT ON;
SET NOCOUNT ON;
IF TRIGGER_NESTLEVEL() > 1 RETURN;
-- For debugging purposes only
PRINT CONVERT(NVARCHAR(MAX), EVENTDATA());
DECLARE @DatabaseName NVARCHAR(128);
SET @DatabaseName = EVENTDATA().value(
'(/EVENT_INSTANCE/DatabaseName)[1]', 'NVARCHAR(128)'
);
DECLARE @Schema NVARCHAR(128);
SET @Schema = EVENTDATA().value(
'(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)'
);
DECLARE @Name NVARCHAR(128);
SET @Name = EVENTDATA().value(
'(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(128)'
);
DECLARE @Definition NVARCHAR(MAX);
SELECT @Definition =
OBJECT_DEFINITION(
OBJECT_ID(
QUOTENAME(@DatabaseName) + '.' +
QUOTENAME(@Schema) + '.' +
QUOTENAME(@Name),
'P'
)
)
;
-- If the sproc is already encrypted, we can't do anything with it
IF @Definition IS NULL RETURN;
SELECT @Definition = STUFF(
@Definition,
CHARINDEX('CREATE', @Definition),
LEN('CREATE'),
'ALTER'
);
IF
@Name LIKE 'SqlQueryNotificationStoredProcedure-%' AND
-- this should always be false since we can't read encrypted definitions,
-- but just to make sure
@Definition NOT LIKE '%WITH ENCRYPTION AS BEGIN%'
BEGIN;
SET @Definition = REPLACE(
@Definition, 'AS' + CHAR(13) + CHAR(10) + 'BEGIN',
'WITH ENCRYPTION AS BEGIN'
);
EXEC (@Definition);
END;
END;
GO
ENABLE TRIGGER [TR_EncryptQueryNotificationProcedures] ON DATABASE;
Disclaimer: not tested against an actual dependency notification, but the basic idea is sound. It's quite brittle because it depends on the exact form of the procedure, of course -- making it more robust is possible, but tedious.
链接地址: http://www.djcxy.com/p/82758.html