ddl触发器无法拦截存储过程执行,仅响应create_procedure等结构变更事件;真正可行的是登录触发器+权限控制组合,或直接收回execute权限并用execute as可控调用。

DDL触发器无法拦截存储过程执行
DDL触发器只响应 CREATE_PROCEDURE、ALTER_PROCEDURE、DROP_PROCEDURE 这类结构变更事件,对 EXEC、sp_executesql 或应用程序发起的运行时调用完全无感知。试图用它“拦截执行”,从 SQL Server 底层机制上就不可行——它根本收不到这类事件。
真正能拦截执行的是登录触发器 + 权限控制组合
SQL Server 没有“执行前拦截存储过程”的原生触发器类型,但你可以通过以下方式实现近似效果:
- 在登录触发器中检查
ORIGINAL_LOGIN()和当前会话的上下文(如APP_NAME()、HOST_NAME()),结合sys.dm_exec_sessions和sys.dm_exec_requests判断是否正在发起目标存储过程调用(需配合sys.dm_exec_sql_text解析最近批处理) - 更可靠的做法是:不依赖触发器,而是直接收回用户对目标存储过程的
EXECUTE权限,只授予特定角色或代理账户;再用EXECUTE AS在受控逻辑中显式切换上下文调用 - 若必须动态拦截,可在每个敏感存储过程开头手动加检查逻辑:
IF NOT EXISTS (SELECT 1 FROM sys.fn_my_permissions(N'dbo.YourProc', N'OBJECT') WHERE permission_name = N'EXECUTE') BEGIN THROW 50000, N'Unauthorized execution', 1; END
为什么别硬套“触发器拦截执行”这个思路
常见错误是把 DDL 触发器和登录触发器混为一谈,误以为只要建个触发器就能卡住 EXEC YourProc。实际上:
-
LOGON触发器只在连接建立时运行一次,无法感知后续任意时刻的存储过程调用 -
rpc_completed扩展事件能捕获执行,但它是事后记录,不能ROLLBACK或阻止执行 - 加密存储过程(
WITH ENCRYPTION)不影响权限校验,也不影响触发器行为——它只是隐藏源码,不绕过执行链路中的权限检查
真正被忽略的关键点是:SQL Server 的执行拦截必须落在权限系统(GRANT/REVOKE)、模块签名(SIGNATURE)或应用层网关上,而不是靠触发器“监听”执行动作。











