首页 > 代码库 > Server级别触发器之login

Server级别触发器之login

一EVENTDATA

EVENTDATA记录登录的相关属性

只有直接在 DDL 或登录触发器内部引用 EVENTDATA 时,EVENTDATA 才会返回数据。如果 EVENTDATA 由其他例程调用(即使这些例程由触发器进行调用),则它将返回 NULL。

在隐式或显式调用 EVENTDATA 的事务提交或回滚之后,EVENTDATA 所返回的数据将无效。

 

二登陆触发器

 

SQL Server 2005

登录触发器将为响应 LOGON 事件而激发存储过程。与 SQL Server 实例建立用户会话时将引发此事件。登录触发器将在登录的身份验证阶段完成之后且用户会话实际建立之前激发。因此,来自触发器内部且通常将到达用户的所有消息(例如错误消息和来自 PRINT 语句的消息)会传送到 SQL Server 错误日志。如果身份验证失败,将不激发登录触发器。

可以使用登录触发器来审核和控制服务器会话,例如通过跟踪登录活动、限制 SQL Server 的登录名或限制特定登录名的会话数。

2.1限制登陆次数

例如,在以下代码中,如果登录名 login_test 已经创建了三个用户会话,登录触发器将拒绝由该登录名启动的 SQL Server 登录尝试。

USE master;
GO
CREATE LOGIN login_test WITH PASSWORD = ‘3KHJ6dhx(0xVYsdf‘ MUST_CHANGE,
    CHECK_EXPIRATION = ON;
GO
GRANT VIEW SERVER STATE TO login_test;
GO
CREATE TRIGGER connection_limit_trigger
ON ALL SERVER WITH EXECUTE AS ‘login_test‘
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN()= ‘login_test‘ AND
    (SELECT COUNT(*) FROM sys.dm_exec_sessions
            WHERE is_user_process = 1 AND
                original_login_name = ‘login_test‘) > 3
    ROLLBACK;
END;

 

 

2.2.登陆记录

可以在登录EVENTDATA属性中查看是否通过应用程序的连接池(is_pooled)

CREATE TABLE [dbo].[tb_login_log](

    [loginname] [varchar](25) NULL,

    [ClientHost] [varchar](50) NULL,

    [IsPooled] [varchar](5) NULL,

    [creattime] [datetime] NULL

)

CREATE TRIGGER [tr_login_log]

ON ALL SERVER WITH EXECUTE AS ‘sa‘

FOR LOGon

AS

BEGIN

 

insert into dbo.tb_login_log(loginname,ClientHost,IsPooled)

SELECT ORIGINAL_LOGIN(),

EVENTDATA().value(‘(/EVENT_INSTANCE/ClientHost)[1]‘,‘NVARCHAR(15)‘),

EVENTDATA().value(‘(/EVENT_INSTANCE/is_pooled)[1]‘,‘VARCHAR(5)‘)

 

END;

 

GO

2.3限制登陆机器IP

1. 限制账号不能在某些IP登录

CREATE TRIGGER [tr_limittest_logon]

ON ALL SERVER WITH EXECUTE AS ‘sa‘

FOR LOGon

AS

BEGIN

IF ORIGINAL_LOGIN()= ‘test‘

----允许test不能在下面的IP登录

AND

(SELECT EVENTDATA().value(‘(/EVENT_INSTANCE/ClientHost)[1]‘, ‘NVARCHAR(15)‘))

IN(‘<local machine>‘,‘99.48.238.162‘,‘99.48.238.176‘)

--commit--解除限制

ROLLBACK;

END;

 

2. 限制账号只能在指定IP登录

create TRIGGER [tr_PermitTestLogonatMakedip]

ON ALL SERVER WITH EXECUTE AS ‘sa‘

FOR logon

AS

BEGIN

--test限制帐号只能在特定IP登陆

IF ORIGINAL_LOGIN()= ‘test‘

----只允许test在下面的IP登录

AND

(SELECT EVENTDATA().value(‘(/EVENT_INSTANCE/ClientHost)[1]‘, ‘NVARCHAR(15)‘))

IN(‘99.48.238.176‘)

commit

else

if --test不在下面的IP登录,则禁止登陆

ORIGINAL_LOGIN()= ‘test‘

AND

(SELECT EVENTDATA().value(‘(/EVENT_INSTANCE/ClientHost)[1]‘, ‘NVARCHAR(15)‘))

not IN(‘99.48.238.176‘)

ROLLBACK;

END;

以上的写法需要判断test在指定IP和不指定IP的两种情况下判断,如果只判断在指定IP的情况之外都rollback则导致其它账号登录也登录不上(因为其它账号都在制定账号和指定IP之外的情况)

所以最优化的方案应该如下:

alter TRIGGER [tr_PermitamsuserLogonatSpecialIP]

ON ALL SERVER WITH EXECUTE AS ‘sa‘

FOR logon

AS

BEGIN

if --amsuser不在下面的IP登录,则禁止登陆

ORIGINAL_LOGIN()= ‘amsuser‘

AND

(SELECT EVENTDATA().value(‘(/EVENT_INSTANCE/ClientHost)[1]‘, ‘NVARCHAR(15)‘))

not IN

(‘<local machine>‘,--

‘*.*.238.176‘,--dbserver

‘*.*.238.164‘,--ams web server

‘*.*.238.165‘,--ams web server

‘*.*.6.122‘--caiding‘s pc

)

ROLLBACK;

else

commit;

END;

 

登录记录触发器现部署在*.*.238.9(CCMS uat)和sccdbservertest(*.*.238.162)

 

登录记录触发器部署在*.*.238.199【sccqzsqluat02101_sql08(pluto\apple)】以测试连接是否启用IsPooled,发现都是没有启用连接池。

Server级别触发器之login