sqlserver 登录记录(登录触发器)

Posted 鱼日文弓虽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sqlserver 登录记录(登录触发器)相关的知识,希望对你有一定的参考价值。

本人自用 sqlserver  账号登录的记录(记录表+登录触发器)

--存储账号的登录记录信息
use [YWmonitor]
go
create table access_log
(
    [code] [int] IDENTITY(1,1) NOT NULL,
    [session_id] [int] NULL,
    [login_time] datetime NULL,
    [host_name] [varchar](50) NULL,
    [original_login_name] [varchar](50) NULL,
    [client_net_address] [varchar](50) NULL,
    CONSTRAINT [PK_access_log] PRIMARY KEY CLUSTERED 
(
    [code] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

--登录触发器设置(确保sa用户可用)
use master
go
CREATE TRIGGER [tr_connection_limit]
ON ALL SERVER WITH EXECUTE AS \'sa\'
FOR LOGON
AS
BEGIN
INSERT INTO [YWmonitor].[dbo].[access_log]
([session_id],[login_time],[host_name],[original_login_name],[client_net_address])
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
END

 登陆触发器能为我们解决什么问题呢?本文将为你讲述5种运用登陆触发器的场景:

1) 限制某登录名(比如sa)只能在本机或者指定的IP中登陆;

2) 限制服务器角色(比如sysadmin)只能在本机或者指定的IP中登陆;

3) 限制某登录名(比如sa)只能某时间段内登陆;

4) 限制登录名与IP的对应关系,支持多对多关系;

5) 限制某登录名可以在某IP段登录

 

下面是借用 ’听风吹雨‘ 的几个常用的触发器设置:

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;

 

--插入测试数据
INSERT [dbo].[ValidLogOn] ([LoginName], [ValidIP]) VALUES (N\'nightworker\', N\'192.168.1.*\')

--创建登录触发器
-- =============================================
-- Author:        <听风吹雨>
-- Create date:    <2013.05.21>
-- Description:    <登陆名和IP过滤,支持IP范围规范>
-- Blog:        <http://www.cnblogs.com/gaizai/>
-- =============================================
CREATE TRIGGER [tr_logon_CheckLogOn_RangeIP]
ON ALL SERVER WITH EXECUTE AS \'sa\'
FOR LOGON
AS
BEGIN
    DECLARE @LoginName sysname
    DECLARE @IP NVARCHAR(15)
    DECLARE @ValidIP NVARCHAR(15)
    DECLARE @len INT
    DECLARE @data XML
    DECLARE @blocked BIT;
    
    SET @len = 0
    SET @blocked = 0
    SET @LoginName = ORIGINAL_LOGIN();
    SET @data = EVENTDATA();
    SET @IP = @data.value(\'(/EVENT_INSTANCE/ClientHost)[1]\', \'NVARCHAR(15)\');
    
    --判断登录名和IP
    IF NOT EXISTS(SELECT [ValidIP] FROM [Logon_DB].[dbo].[ValidLogOn] WHERE [LoginName] = @LoginName AND [ValidIP] = @IP) 
    BEGIN
        --是否存在IP范围匹配
        SET @ValidIP = (SELECT TOP 1 [ValidIP] FROM [Logon_DB].[dbo].[ValidLogOn] 
            WHERE [LoginName] = @LoginName AND [ValidIP] LIKE \'%[*]\');
        --如果存在就替换Client的IP
        IF (CHARINDEX(\'*\',@ValidIP) > 0 AND @IP <> \'<local machine>\' AND @IP <> \'127.0.0.1\')
        BEGIN
            DECLARE @SubValidIP NVARCHAR(15)
            SET @SubValidIP = SUBSTRING(@ValidIP,0,CHARINDEX(\'*\',@ValidIP))
            SET @len = LEN(@SubValidIP) + 1
            IF(SUBSTRING(@IP,0,@len) != @SubValidIP)
            BEGIN
                ROLLBACK;
                SET @blocked = 1
            END
        END
        ELSE
        BEGIN
            ROLLBACK;
            SET @blocked = 1
        END
    END

    --日志记录
    INSERT INTO [Logon_DB].[dbo].[LogonLog]
        ([session_id]
        ,[login_time]
        ,[host_name]
        ,[original_login_name]
        ,[client_net_address]
        ,[XmlEvent]
        ,[Blocked])
    SELECT 
        @data.value(\'(/EVENT_INSTANCE/SPID)[1]\', \'smallint\'),
        GETDATE(),
        @data.value(\'(/EVENT_INSTANCE/ServerName)[1]\', \'sysname\'),
        @data.value(\'(/EVENT_INSTANCE/LoginName)[1]\', \'sysname\'),
        @data.value(\'(/EVENT_INSTANCE/ClientHost)[1]\', \'NVARCHAR(15)\'),
        @data,@blocked
END;

数据库操作记录触发器设计举例:

--创建表:VERSION_CONTROL_TABLE

CREATE TABLE [dbo].[VERSION_CONTROL_TABLE](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [databasename] [varchar](256) NULL,
    [eventtype] [varchar](50) NULL,
    [objectname] [varchar](256) NULL,
    [objecttype] [varchar](25) NULL,
    [sqlcommand] [nvarchar](max) NULL,
    [loginname] [varchar](256) NULL,
    [hostname] [varchar](256) NULL,
    [PostTime] [datetime] NULL,
    [Version] [int] NOT NULL,
 CONSTRAINT [PK_VERSION_CONTROL_TABLE] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

  ---创建触发器:TRG_VERSION_CONTROL_TABLE

 

CREATE TRIGGER [TRG_VERSION_CONTROL_TABLE]
ON DATABASE
FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE,
CREATE_TABLE, ALTER_TABLE, DROP_TABLE,
CREATE_FUNCTION, ALTER_FUNCTION, DROP_FUNCTION,
CREATE_TRIGGER, ALTER_TRIGGER, DROP_TRIGGER,
CREATE_VIEW, ALTER_VIEW, DROP_VIEW,
CREATE_INDEX, ALTER_INDEX, DROP_INDEX
 
AS
 
SET NOCOUNT ON
 
DECLARE @CurrentVersion int
DECLARE @CurrentID int
DECLARE @DatabaseName varchar(256)
DECLARE @ObjectName varchar(256)
DECLARE @data XML
 
SET @data = EVENTDATA()
INSERT INTO dbo.VERSION_CONTROL_TABLE(databasename, eventtype,objectname, objecttype, sqlcommand, loginname,Hostname,PostTime, Version)
VALUES(
@data.value(\'(/EVENT_INSTANCE/DatabaseName)[1]\', \'varchar(256)\'),
@data.value(\'(/EVENT_INSTANCE/EventType)[1]\', \'varchar(50)\'),  -- value is case-sensitive
@data.value(\'(/EVENT_INSTANCE/ObjectName)[1]\', \'varchar(256)\'), 
@data.value(\'(/EVENT_INSTANCE/ObjectType)[1]\', \'varchar(25)\'), 
@data.value(\'(/EVENT_INSTANCE/TSQLCommand)[1]\', \'varchar(max)\'), 
@data.value(\'(/EVENT_INSTANCE/LoginName)[1]\', \'varchar(256)\'),
HOST_NAME(),
GETDATE(),
0
)
SET @CurrentID = IDENT_CURRENT(\'VERSION_CONTROL_TABLE\')
SELECT @DatabaseName = databasename, @ObjectName = objectname FROM VERSION_CONTROL_TABLE WHERE ID = @CurrentID
IF (@DatabaseName IS NOT NULL AND @ObjectName IS NOT NULL)
BEGIN
    SELECT @CurrentVersion = MAX(Version) FROM VERSION_CONTROL_TABLE WHERE databasename = @DatabaseName AND objectname = @ObjectName
    UPDATE VERSION_CONTROL_TABLE SET Version = ISNULL(@CurrentVersion, 0) + 1 WHERE ID = @CurrentID
END

 

以上是关于sqlserver 登录记录(登录触发器)的主要内容,如果未能解决你的问题,请参考以下文章

SQLServer限制IP,限制用户,限制SSMS登录

[转帖]SQLSERVER 使用触发器实现 禁用sa用户 在非本机登录

Server级别触发器之login

登录触发器之控制IP与用户登录记录登录日志

oracle通过触发器实现登录登出日志记录

如何防止片段在活动重新创建时触发 onCreate onCreateView