必须用 BEFORE LOGON ON DATABASE 触发器,因它在身份验证后、会话分配前执行,RAISE_APPLICATION_ERROR 可彻底终止登录;AFTER LOGON 已创建会话,异常仅中断后续操作,用户仍持有有效连接。

必须用 BEFORE LOGON ON DATABASE 触发器,且只对普通用户生效;AFTER LOGON 无法真正阻止连接,只会报 ORA-00604 并留下已建立的会话。
为什么非得用 BEFORE LOGON 而不是 AFTER LOGON
Oracle 在完成身份验证后、分配会话资源前执行 BEFORE LOGON,此时抛出 RAISE_APPLICATION_ERROR 可彻底终止登录流程;而 AFTER LOGON 已完成会话初始化,异常仅中断后续环境设置,用户仍持有有效会话(尤其在 JDBC 连接池或自动重连场景下极易被忽略)。
-
BEFORE LOGON触发时,V$SESSION中尚无该会话记录,无递归 SQL 风险 -
AFTER LOGON中若做 INSERT 审计日志,会触发隐式事务,极可能引发ORA-00604+ORA-01031 - 测试时若用
conn / as sysdba,SYS 用户默认绕过所有登录触发器,务必换普通用户验证
时间判断逻辑怎么写才不被 NLS 设置坑
Oracle 的 TO_CHAR(SYSDATE, 'D') 返回值依赖 NLS_TERRITORY:美国默认周日=1,中国常设周一=1。生产环境不能赌配置,必须显式指定语言:
- 用
TO_CHAR(SYSDATE, 'D', 'NLS_DATE_LANGUAGE=AMERICAN')—— 周日=1,周一=2,…,周六=7 - 小时必须用
TO_CHAR(SYSDATE, 'HH24'),字符串比较即可:'08'到'17'覆盖 08:00–17:59 - 避免
TO_NUMBER()转换:隐式类型转换在触发器中易失败,且无必要 - 别查表、别调自定义函数——所有逻辑必须纯计算,否则触发
ORA-00604
审计记录要写进表?先看权限和字段长度
触发器以定义者权限(DEFINER'S RIGHTS)运行,但插入目标表需要显式授权;且常见字段长度陷阱会导致静默失败:
- IP 地址字段必须为
VARCHAR2(46),否则 IPv6(如2001:db8::1)会截断或报ORA-06502 - 执行
GRANT INSERT ON audit_login_log TO SYS;(若触发器由 SYS 创建) - INSERT 语句中不能用
:NEW或:OLD——LOGON触发器无行上下文,用SYS_CONTEXT('USERENV', 'IP_ADDRESS')和USER - 若 IP 总是
NULL,不是触发器问题,而是客户端走代理/负载均衡,Oracle 收不到真实地址
DBA 用户必须放行,否则自己也登不进去
触发器里第一件事就是跳过高权限账号,否则维护窗口一到,所有人包括 DBA 全被锁死:
- 硬编码放行列表:
IF USER IN ('SYS', 'SYSTEM', 'DBSNMP') THEN RETURN; - 不要用角色判断(如
IS_MEMBER('DBA')),触发器内无法执行角色查询 - 检查触发器状态:
SELECT trigger_name, status FROM dba_triggers WHERE triggering_event = 'LOGON';,确保是ENABLED - RAC 环境需确认是否在所有实例上创建并启用,否则部分节点不受控
真正难的不是写触发器,而是让时间判断逻辑在所有数据库实例、所有 NLS 配置、所有网络拓扑下都稳定返回预期值;一旦漏掉 NLS_DATE_LANGUAGE 或 IP 字段长度,问题会在凌晨三点爆发,且日志里只留一条模糊的 ORA-00604。


















