LOGON触发器工作原理
登录触发器将为响应 LOGON 事件而激发存储过程。 与 SQL Server实例建立用户会话时将引发此事件。 登录触发器将在登录的身份验证阶段完成之后且用户会话实际建立之前激发。 因此,来自触发器内部且通常将到达用户的所有消息(例如错误消息和来自 PRINT 语句的消息)会传送到 SQL Server 错误日志。 如果身份验证失败,将不激发登录触发器。
LOGON触发器创建
语法:
--登录触发器在服务器对象-》触发器中查看
--声明数据库引用
use 数据库名;
go
--判断是否存在登录触发器,如果存在则删除
if exists(select * from sys.server_triggers where name=触发器名)
drop trigger 触发器名 on all server;
go
--创建触发器
create
--触发器标识符
trigger
--触发器名称
触发器名
on
--适用范围: SQL Server 2008 到 SQL Server 2017。
--将 DDL 或登录触发器的作用域应用于当前服务器。 如果指定了此参数,则只要当前服务器中的任何位置出现 event_type 或 event_group,就会激发该触发器。
all server
with
--适用范围: SQL Server 2008 到 SQL Server 2017。
--对 CREATE TRIGGER 语句的文本进行模糊处理。 使用 WITH ENCRYPTION 可以防止将触发器作为 SQL Server 复制的一部分进行发布。 不能为 CLR 触发器指定 WITH ENCRYPTION。
encryption,
--EXECUTE AS Clause
--{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }
--CALLER
--指定模块内的语句在模块调用方的上下文中执行。 执行模块的用户不仅必须对模块本身拥有适当的权限,还要对模块引用的任何数据库对象拥有适当权限。
--CALLER 是除队列外的所有模块的默认值,与 SQL Server 2005 行为相同。
--CALLER 不能在 CREATE QUEUE 或 ALTER QUEUE 语句中指定。
--SELF
--EXECUTE AS SELF 与 EXECUTE AS user_name 等价,其中指定用户是创建或更改模块的用户。 创建或更改模块的用户的实际用户 ID 存储在 sys.sql_modules 或 sys.service_queues 目录视图的 execute_as_principal_id 列中。
--SELF 是队列的默认值。
--OWNER
--指定模块内的语句在模块的当前所有者上下文中执行。 如果模块没有指定的所有者,则使用模块架构的所有者。 不能为 DDL 或登录触发器指定 OWNER。
--' user_name '
--指定模块内的语句在 user_name 指定的用户的上下文中执行。 将根据 user_name 来验证对模块内任意对象的权限。 不能为具有服务器作用域的 DDL 触发器或登录触发器指定 user_name。 请改用 login_name。
--user_name 必须存在于当前数据库中,并且必须是单一实例帐户。 user_name 不能为组、角色、证书、密钥或内置帐户,如 NT AUTHORITYLocalService、NT AUTHORITYNetworkService 或 NT AUTHORITYLocalSystem。
--执行上下文的用户 ID 存储在元数据中,可以在 sys.sql_modules 或 sys.assembly_modules 目录视图的 execute_as_principal_id 列查看。
execute as 'username'
--FOR | AFTER
--AFTER 指定 DML 触发器仅在触发 SQL 语句中指定的所有操作都已成功执行时才被触发。 所有的引用级联操作和约束检查也必须在激发此触发器之前成功完成。
--如果仅指定 FOR 关键字,则 AFTER 为默认值。
--不能对视图定义 AFTER 触发器。
{ for | after }
--登录触发器标识符
logon
as
begin
sql_statement;
end
示例:本示例演示服务器只允许登录三个人,超过第三个人不允许登录。
--登录触发器在服务器对象-》触发器中查看
--声明数据库引用
use testss;
go
--判断是否存在登录触发器,如果存在则删除
if exists(select * from sys.server_triggers where name='logintri')
drop trigger logintri on all server;
go
--创建触发器
create
--触发器标识符
trigger
--触发器名称
logintri
on
--适用范围: SQL Server 2008 到 SQL Server 2017。
--将 DDL 或登录触发器的作用域应用于当前服务器。 如果指定了此参数,则只要当前服务器中的任何位置出现 event_type 或 event_group,就会激发该触发器。
all server
with
--适用范围: SQL Server 2008 到 SQL Server 2017。
--对 CREATE TRIGGER 语句的文本进行模糊处理。 使用 WITH ENCRYPTION 可以防止将触发器作为 SQL Server 复制的一部分进行发布。 不能为 CLR 触发器指定 WITH ENCRYPTION。
encryption,
--EXECUTE AS Clause
--{ EXEC | EXECUTE } AS { SELF | OWNER | 'user_name' }
--CALLER
--指定模块内的语句在模块调用方的上下文中执行。 执行模块的用户不仅必须对模块本身拥有适当的权限,还要对模块引用的任何数据库对象拥有适当权限。
--CALLER 是除队列外的所有模块的默认值,与 SQL Server 2005 行为相同。
--CALLER 不能在 CREATE QUEUE 或 ALTER QUEUE 语句中指定。
--SELF
--EXECUTE AS SELF 与 EXECUTE AS user_name 等价,其中指定用户是创建或更改模块的用户。 创建或更改模块的用户的实际用户 ID 存储在 sys.sql_modules 或 sys.service_queues 目录视图的 execute_as_principal_id 列中。
--SELF 是队列的默认值。
--OWNER
--指定模块内的语句在模块的当前所有者上下文中执行。 如果模块没有指定的所有者,则使用模块架构的所有者。 不能为 DDL 或登录触发器指定 OWNER。
--' user_name '
--指定模块内的语句在 user_name 指定的用户的上下文中执行。 将根据 user_name 来验证对模块内任意对象的权限。 不能为具有服务器作用域的 DDL 触发器或登录触发器指定 user_name。 请改用 login_name。
--user_name 必须存在于当前数据库中,并且必须是单一实例帐户。 user_name 不能为组、角色、证书、密钥或内置帐户,如 NT AUTHORITYLocalService、NT AUTHORITYNetworkService 或 NT AUTHORITYLocalSystem。
--执行上下文的用户 ID 存储在元数据中,可以在 sys.sql_modules 或 sys.assembly_modules 目录视图的 execute_as_principal_id 列查看。
execute as 登录名
--FOR | AFTER
--AFTER 指定 DML 触发器仅在触发 SQL 语句中指定的所有操作都已成功执行时才被触发。 所有的引用级联操作和约束检查也必须在激发此触发器之前成功完成。
--如果仅指定 FOR 关键字,则 AFTER 为默认值。
--不能对视图定义 AFTER 触发器。
for
--登录触发器标识符
logon
as
begin
if (select count(1) from sys.dm_exec_sessions where is_user_process=1 and original_login_name=登录名) >3 and original_login()=登录名
begin
rollback;
end
end
示例结果:
LOGON登录触发器优缺点
优点:
1、可以使用登录触发器来审核和控制服务器会话。
2、通过跟踪登录活动、限制 SQL Server的登录名或限制特定登录名的会话数。
3、防止数据库账号密码泄露或者不合法的IP登录。
缺点:
1、登录可能引起不必要的触发逻辑。
2、登录触发器创建的会话是实例级别,并且应用于所有服务器,可能会对新建数据库和会话产生不必要的影响。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。