Tìm danh tính của khách hàng bắn một truy vấn trong SQL Server mà không sử dụng kích hoạt?


11

Tôi hiện đang sử dụng Change Data Capture (CDC) để theo dõi các thay đổi dữ liệu và tôi muốn theo dõi tên máy chủ và địa chỉ IP của máy khách gửi truy vấn đã thực hiện các thay đổi. Nếu có 5 khách hàng khác nhau đăng nhập thông qua cùng một tên người dùng, một người sẽ phải đối mặt với câu hỏi hóc búa trong số 5 khách hàng đã truy vấn. Các giải pháp chuyên sâu khác mà tôi tìm thấy bao gồm thay đổi bảng CDC bằng lệnh sau:

ALTER TABLE cdc.schema_table_CT 
ADD HostName nvarchar(50) NULL DEFAULT(HOST_NAME())

Tuy nhiên, điều này trả về tên máy chủ của máy chủ nơi truy vấn được kích hoạt và không phải tên máy chủ của máy khách thực hiện truy vấn.

Có cách nào xung quanh vấn đề này? Một cái gì đó sẽ giúp đăng nhập tên máy chủ hoặc địa chỉ IP (hoặc một số loại nhận dạng duy nhất khác) của khách hàng. Tôi không muốn sử dụng các kích hoạt, vì nó làm chậm hệ thống, CDC cũng tạo ra các bảng hệ thống, do đó, việc kích hoạt trên đó rõ ràng là không thể.

Câu trả lời:


4

Tôi không chắc chắn về CDC, nhưng nếu đăng nhập view server state permissionbạn có thể sử dụng DMV để có được một số thông tin.

Điều này được đưa ra trong Sách trực tuyến ở đây . Tôi đã thay đổi truy vấn để thêm các cột sẽ cung cấp cho bạn IP address:

SELECT 
    c.session_id, c.net_transport, c.encrypt_option, c.auth_scheme,
    s.host_name, s.program_name, s.client_interface_name,
    c.local_net_address, c.client_net_address, s.login_name, s.nt_domain, 
    s.nt_user_name, s.original_login_name, c.connect_time, s.login_time 
FROM sys.dm_exec_connections AS c
JOIN sys.dm_exec_sessions AS s
    ON c.session_id = s.session_id
WHERE c.session_id = SPID;  --session ID you want to track

4

Khi bạn nói, "không sử dụng kích hoạt", bạn có nghĩa là bất kỳ kích hoạt hoặc chỉ kích hoạt từng hàng trên bảng?

Tôi yêu cầu bởi vì bạn thể có được những gì bạn muốn với việc sử dụng CONTEXT_INFO()chức năng một cách thận trọng , nhưng bạn sẽ cần đảm bảo rằng nó SET CONTEXT_INFOđược gọi chính xác trước khi hoạt động của bạn diễn ra.

Một nơi để làm điều đó có thể là trình kích hoạt đăng nhập cấp máy chủ (nghĩa là không phải là trình kích hoạt cơ sở dữ liệu / mức đối tượng), như vậy:

USE master
GO
CREATE TRIGGER tr_audit_login
ON ALL SERVER 
WITH EXECUTE AS 'sa'
AFTER LOGON
AS BEGIN
    BEGIN TRY

        DECLARE @eventdata XML = EVENTDATA();

        IF @eventdata IS NOT NULL BEGIN
            DECLARE @spid INT;
            DECLARE @client_host VARCHAR(64);
            SET @client_host    = @eventdata.value('(/EVENT_INSTANCE/ClientHost)[1]',   'VARCHAR(64)');
            SET @spid           = @eventdata.value('(/EVENT_INSTANCE/SPID)[1]',         'INT');

            -- pack the required data into the context data binary
            -- (spid is just an example of packing multiple data items in a single field: you would probably use @@SPID at the point of use, instead)
            DECLARE @context_data VARBINARY(128);
            SET @context_data = CONVERT(VARBINARY(4),  @spid)
                              + CONVERT(VARBINARY(64), @client_host);

            -- persist the spid and host into session-level memory
            SET CONTEXT_INFO @context_data;             
        END

    END TRY
    BEGIN CATCH
        /* do better error handling here...
         * logon trigger can lock all users out of server, so i am just swallowing everything
         */
        DECLARE @msg NVARCHAR(4000) = ERROR_MESSAGE();
        RAISERROR('%s', 10, 1, @msg) WITH LOG;
    END CATCH
END

Sau đó, bạn có thể thêm các ràng buộc mặc định vào bảng của mình, để lưu trữ ngữ cảnh (đối với tốc độ chèn):

ALTER TABLE cdc.schema_table_CT 
ADD ContextInfo varbinary(128) NULL DEFAULT(CONTEXT_INFO())

Khi bạn đã có điều đó, bạn có thể truy vấn ContextInfocột đó với một chút xúc xắc:

SELECT *
    ,spid = CONVERT(INT, SUBSTRING(ContextInfo, 1, 4))
    ,client = CONVERT(VARCHAR(64), SUBSTRING(ContextInfo, 5, 64))
FROM cdc.schema_table_CT

Về mặt kỹ thuật, bạn có thể làm điều đó SUBSTRINGvà xử lý CONVERTnhư một phần của ràng buộc mặc định của mình và chỉ lưu trữ IP của máy khách ở đó, nhưng có thể nhanh hơn để lưu trữ toàn bộ bối cảnh ở đó (như được thực hiện trên mọi INSERT) và chỉ trích xuất các giá trị trong một SELECTkhi bạn cần chúng

Tôi có thể có xu hướng bọc tất cả các cuộc gọi của tôi SUBSTRINGCONVERTtrong một hàm có giá trị bảng nội tuyến một hàng, mà tôi sẽ làm CROSS APPLYkhi cần thiết. Điều đó giữ logic giải nén ở một nơi:

CREATE FUNCTION fn_context (
    @context_info VARBINARY(128)
)
RETURNS TABLE
AS RETURN (
    SELECT
         spid = CONVERT(INT, SUBSTRING(@context_info, 1, 4))
        ,client = CONVERT(VARCHAR(64), SUBSTRING(@context_info, 5, 64))
)
GO

SELECT * 
FROM cdc.schema_table_CT s
CROSS APPLY dbo.fn_context(s.ContextInfo) c

Lưu ý rằng đó CONTEXT_INFOchỉ là 128 byte VARBINARY. Nếu bạn cần nhiều dữ liệu hơn mức bạn có thể chứa 128 byte, tôi sẽ tạo một bảng để chứa tất cả dữ liệu đó, chèn dưới dạng hàng cho 'phiên' đó vào bảng trong trình kích hoạt đăng nhập và đặt thành CONTEXT_INFOgiá trị khóa thay thế của bảng đó

Bạn cũng nên lưu ý rằng, vì nó chỉ là một ràng buộc mặc định, nên người dùng có đặc quyền phù hợp sẽ ghi đè lên dữ liệu ngữ cảnh đó trong bảng at-rest. Tất nhiên, điều tương tự cũng đúng với tất cả các cột khác trong các bảng kiểu 'kiểm toán'.

Sẽ thật tuyệt nếu nó có thể là một cột được tính toán bền vững, thay vì mặc định, nhưng CONTEXT_INFO()chức năng này không mang tính quyết định, vì vậy nó là không nên (bạn có thể sử dụng một số FUNCTIONmánh khóe xung quanh VIEW, nhưng tôi sẽ không ).

Nó cũng không quan trọng đối với người dùng đó có đủ quyền truy cập để SET CONTEXT_INFOtự gọi và làm xáo trộn ngày của bạn (ví dụ: với các giá trị giả hoặc tiêm lưu trữ được chế tạo đặc biệt), vì vậy hãy đối xử với sự nghi ngờ và quan tâm, mã hóa nó trước khi hiển thị và xử lý các trường hợp ngoại lệ tốt.

Đối với tên máy chủ, tôi nghĩ ClientHostyếu tố EVENTDATA()cung cấp cho bạn địa chỉ IP (hoặc <local machine>chỉ báo). Mặc dù về mặt kỹ thuật bạn có thể sử dụng CLR để thực hiện tra cứu DNS ngược trở lại tên máy chủ, nhưng chúng có xu hướng quá chậm để thực hiện INSERT, vì vậy tôi khuyên bạn không nên làm như vậy.

Nếu bạn phải có tên máy chủ, bạn có thể muốn sử dụng công việc Tác nhân SQL để định kỳ điền vào một bảng riêng với các hợp đồng thuê hiện tại từ máy chủ DHCP cục bộ hoặc tệp vùng DNS, như một quy trình ngoài băng tần và LEFT JOINtrong đó các truy vấn trong tương lai (hoặc bọc trong một vô hướng FUNCTIONđể cung cấp một giá trị cho một ràng buộc mặc định, theo thời gian).

Một lần nữa, bạn cần lưu ý rằng, nếu ứng dụng có bất kỳ loại thành phần nào đối mặt với công chúng, địa chỉ IP và tên máy chủ không đáng tin cậy (ví dụ do NAT). Ngay cả khi nó không phải là đối tượng công khai, vẫn có một thành phần dựa trên thời gian nhất định đối với hầu hết các bản đồ IP / tên máy chủ, mà bạn có thể cần phải tính đến.

Cuối cùng, trước khi thực hiện kích hoạt đăng nhập của bạn, có thể đáng để bật kết nối quản trị viên chuyên dụng của máy chủ của bạn. Nếu kích hoạt đăng nhập bị hỏng theo bất kỳ cách nào, nó có thể ngăn tất cả người dùng đăng nhập (bao gồm cả tài khoản sysadmin):

USE master
GO
-- you may want to do this, so you have a back-out if the login trigger breaks login
EXEC sp_configure 'remote admin connections', 1 
GO
RECONFIGURE
GO

Nếu bạn bị khóa, có thể sử dụng DAC để thả hoặc vô hiệu hóa trình kích hoạt đăng nhập:

C:\> sqlcmd -S localhost -d master -A
1> DISABLE TRIGGER tr_audit_login ON ALL SERVER
2> GO

3

Vui lòng xem lỗi kết nối : Dưới đây là đoạn trích có liên quan từ nó

Hành vi này là do thiết kế. CDC được thiết kế để hiển thị các thông tin sau về thay đổi: các cột được cập nhật, loại hoạt động và thông tin giao dịch. Nó đã không được thiết kế như một giải pháp kiểm toán. Nó đã được tạo ra để cho phép giải pháp Trích xuất và Tải (ETL) hiệu quả thông qua tải dữ liệu gia tăng, là chìa khóa để giảm thời gian ETL tổng thể. Mục tiêu chính của nó là phơi bày "những gì đã thay đổi" chứ không phải ai, khi ... Tôi khuyên bạn nên sử dụng tính năng Kiểm toán SQL.

Cho đến nay, không có kế hoạch chuyển đổi CDC trong giải pháp Kiểm toán.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.