一、背景
在MySQL的mysql.User表保存了登陸用戶的權限信息,Host和User字段則是關於登陸IP的限制。但是在SQL Server沒有這樣一個表,那SQL Server有什麼辦法可以實現類似的安全控制的功能呢?
SQL Server 包括三種常規類型的觸發器:DML觸發器、DDL觸發器和登錄觸發器。DML觸發器是比較常使用的,它通常在表或視圖中修改數據(INSERT、UPDATE和DELETE 等)為了保證業務數據的完整性和一致性,可以對事務進行回滾等操作;如果你對DDL觸發器感興趣,可以參考:SQL Server DDL觸發器運用,裡面涉及到DDL觸發器的知識;登陸觸發器將在本文運用到關於IP登陸限制的解決方案中。
登陸觸發器能為我們解決什麼問題呢?本文將為你講述5種運用登陸觸發器的場景:
1) 限制某登錄名(比如sa)只能在本機或者指定的IP中登陸;
2) 限制服務器角色(比如sysadmin)只能在本機或者指定的IP中登陸;
3) 限制某登錄名(比如sa)只能某時間段內登陸;
4) 限制登錄名與IP的對應關系,支持多對多關系;
5) 限制某登錄名可以在某IP段登錄(比如192.168.1.*),如下圖;
二、實現過程
(一) 我機器的IP是:192.168.1.48,首先我在數據庫創建一個test帳號,設置密碼為123,接著創建登陸觸發器:tr_connection_limit,它會在用戶登陸的時候觸發,通過EVENTDATA()函數返回的客戶端的IP,使用ORIGINAL_LOGIN()函數返回的登陸名,對IP和登錄名進行判斷。
當登錄名是test的時候,如果登陸的IP地址本地<local machine>或者是192.168.1.50,192.168.1.120就允許登陸,在這之外其它情況的登陸將回滾。登陸失敗的如Figure1所示。
--Script1:創建test登錄賬號 CREATE LOGIN test WITH PASSWORD = '123' GO -- ============================================= -- Author: <聽風吹雨> -- Create date: <2013.05.21> -- Description: <限制test用戶只能在本機和指定的IP中登陸> -- Blog: <http://www.cnblogs.com/gaizai /> -- ============================================= CREATE TRIGGER [tr_connection_limit] ON ALL SERVER WITH EXECUTE AS 'sa' FOR LOGON AS BEGIN --限制test這個帳號的連接 IF ORIGINAL_LOGIN()= 'test' --允許test在本機和下面的IP登錄 AND (SELECT EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(15)')) NOT IN('<local machine>','192.168.1.50','192.168.1.120') ROLLBACK; END;
(Figure1:test用戶登陸錯誤信息)
我在一台IP為192.168.1.115的機器上使用test登陸名登陸我的SQL Server數據庫,因為這個IP不在允許的IP列表中,所以出現了Figure1的錯誤信息。我再使用一台IP為192.168.1.120的機器登陸我的SQL Server數據庫,成功登陸了,使用Script2返回登陸的信息;如Figure2,請看session_id為58的記錄:登陸名為test,登陸的IP為192.168.1.120。
--Script2:返回登錄信息 SELECT a.[session_id],a.[login_time],a.[host_name], a.[original_login_name],b.[client_net_address] FROM MASTER.sys.dm_exec_sessions a INNER JOIN MASTER.sys.dm_exec_connections b ON a.session_id=b.session_id
(Figure2:用戶登陸信息)
關於Script1腳本中EXECUTE AS的用法可以參考:EXECUTE AS (Transact-SQL),ORIGINAL_LOGIN()函數可以參考:ORIGINAL_LOGIN (Transact-SQL),EVENTDATA()函數用法可以參考:EVENTDATA (Transact-SQL)