logon failed due to trigger execution

前幾天在公司數據庫布了一個觸發器,用來審計所有鏈接到數據庫的賬號信息。
腳本如下:

CREATE TABLE master..Login_Info

(       Login_Name           NVARCHAR(256),
       Login_Time           DATETIME,
       Host_Name            NVARCHAR(128)
)
go


 CREATE TRIGGER tr_logon_audit
ON ALL SERVER 
FOR LOGON
AS
BEGIN
       INSERT INTO Login_Info
       SELECT ORIGINAL_LOGIN(), GETDATE(),
       EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]','NVARCHAR(128)')
END

select * from master.dbo.Login_Info

該觸發器創建後,數據庫連接開始陸續有報錯信息,此時,除了dba用戶外,其餘用戶都無法登錄,報錯信息如下:
這裏寫圖片描述

臨時禁用觸發器後,該問題得到解決。
在網上搜到解決辦法如下,即在all server 後面添加“WITH EXECUTE AS ‘sa’”。否則,只有DBA賬號可以登錄。
(https://sqlandme.com/2011/07/13/sql-server-login-auditing-using-logon-triggers/)
重新部署後,運行沒有問題。腳本如下:

 CREATE TRIGGER tr_logon_audit
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
       INSERT INTO Login_Info
       SELECT ORIGINAL_LOGIN(), GETDATE(),
       EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]','NVARCHAR(128)')
END

本以爲這件事到這裏就結束了。
但是在一週後,突然接到開發人員反饋:PYTHON程序連接數據庫時報錯:logon failed due to trigger execution。但是並未收到其他程序的報錯。
由於報錯原因尚未查明,我到服務器上去禁用此觸發器。此時我用的圖形化界面而不是TSQL語句。
然後就出問題了。。。

我的數據庫卡住了.當我重新登錄數據庫時,報錯信息如下,我已無法重新登錄SSMS,且任何其他賬號也無法重新登錄。無法使用SSMS,意味着我無法通過TSQL或圖形化界面去處理問題,意味着該問題得不到解決,所有對數據庫的訪問都將被拒絕。
OH MY GOD!
這裏寫圖片描述

幸運的是在網上找到了解決辦法。
(感謝:https://blog.sqlauthority.com/2009/06/27/sql-server-fix-error-17892-logon-failed-for-login-due-to-trigger-execution-changed-database-context-to-master/
在使用SSMS無法登陸到數據庫的情況下,可以通過DAC連接數據庫。(DAC是當與服務器的標準連接不可用時,爲管理員提供的特殊的診斷連接)。
詳細信息見:https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/diagnostic-connection-for-database-administrators?view=sql-server-2017
當我無法連接到SSMS以刪除或禁用觸發器時,此時只能通過DAC連接強制刪除TRIGGER.
這裏寫圖片描述

 sqlcmd -S LocalHost -d master -A 
1> DROP TRIGGER Tr_ServerLogon ON ALL SERVER 
2> GO

刪除觸發器後重新登錄SSMS,發現此時已經可以登錄,trigger已被刪除。
又是一番在查資料。最終在 Microsoft Support 找到一篇文章,上面提到了EVENTDATA function有可能會造成登錄出錯。先不細究原因,把trigger 腳本做如下修改:

CREATE TRIGGER [tr_logon_audit]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
INSERT INTO Login_Info
SELECT ORIGINAL_LOGIN(), GETDATE()
,HOST_NAME
--EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]','NVARCHAR(128)')
FROM MASTER.sys.dm_exec_sessions a 
WHERE a.session_id = @@SPID 
END

重新啓用後,python程序連接正常。
詳細研究文檔發現,解釋的原因如下:
該函數返回XML,且區分大小寫。但是用戶並沒有區分大小寫,因此所有的EVENTDATA函數總是返回NULL,且所有sa等價登錄都被拒絕訪問。
這裏寫圖片描述

但是爲什麼只有python連接報錯?這個還要繼續研究。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章