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:

  • Convince the customer that it doesn't matter that the auto generated procedure is unencrypted because it only does cleanup work and contains no real information (thanks to ScottChamberlain for pointing this out).
  • Find a way to encrypt the stored procedure generated by SqlDependency.
  • 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

    上一篇: 如何通过在modulus.io上托管的流星应用程序来使用spiderable

    下一篇: 加密由SqlDependency创建的存储过程