曾有同学问过,能不能知道都有谁登陆过Oracle数据库, 碰巧看到老杨的这篇历史文章《Oracle中如何记录访问数据库的登陆信息》,介绍了几种实现这个需求的方案,学习一下。

1. 有哪些审计的方案?

说的再通俗点就是:数据库用户的登录记录,如何查看?

一般有三种方案:

(1) 使用trigger定制化用系统触发器来记录用户登录。

(2) 开启库audit审计功能用Oracle库本身的审记功能来记录用户的操作信息。

(3) 使用logmnr进行挖取日志分析从logminner的文件中抓取出用户登录信息。

2. 如何实现上述审计?

方案一,使用trigger定制化

具体操作如下:

(1) 创建表空间

CREATE TABLESPACE logInfo DATAFILE'/oradata/group/logInfo_01.dbf' SIZE 1G AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED
LOGGING
ONLINE
EXTENT MANAGEMENT LOCAL AUTOALLOCATE
BLOCKSIZE 8K
SEGMENT SPACE MANAGEMENT AUTO
FLASHBACK ON;

(2) 创建用户登录表,并指定表空间为logInfo

CREATE TABLE LOGINFO_LOG
(SESSION_ID                    NUMBER(8,0) NOT NULL,LOGIN_ON_TIME                 DATE,LOGIN_OFF_TIME                DATE,USER_IN_DB                    VARCHAR2(50),MACHINE                       VARCHAR2(50),IP_ADDRESS                    VARCHAR2(20),RUN_PROGRAM                   VARCHAR2(50)
)
PCTFREE 10
PCTUSED 40
MAXTRANS 255
TABLESPACE logInfo
STORAGE(INITIAL 64K MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
NOCACHE
LOGGING
/

(3) 创建用户登录触发器

CREATE OR REPLACE TRIGGER sys.LOGIN_ON_INFO
AFTER LOGON
ON DATABASE
BEGININSERT into LOGINFO_LOG(session_id,login_on_time,login_off_time,user_in_db,machine,ip_address,run_program)SELECT AUDSID,sysdate,null,sys.login_user,machine,SYS_CONTEXT('USERENV','IP_ADDRESS'),programFROM v$session WHERE AUDSID=USERENV('SESSIONID');
END;
/

(4) 创建登出信息触发器

CREATE OR REPLACE TRIGGER SYS.LOGIN_OFF_INFO
BEFORE LOGOFF
ON DATABASE
Beginupdate sys.LOGINFO_LOG set login_off_time=sysdate where session_id=USERENV('SESSIONID');exception when others thennull;
END;
/

(5) 查看登陆信息

Select * from loginfo_log order by 2 desc;

可在$ORACLE_HOME/network/admin/sqlnet.ora中设置访问限制,

-- 启动检查
tcp.validate_checking=yes
-- 允许访问
tcp.invited_nodes=(IP1,IP2,….)
-- 拒绝访问
tcp.excluded_nodes=(IP1,IP2,…..)

此外,因为应用程序中的delete、drop、update操作也需要记录,如下以drop审计进行举例,说明使用触发器如何进行用户操作的留痕。

(1) 创建drop操作的用户留痕表

CREATE TABLE DROP_LOG
(SESSION_ID     INT NOT NULL,DROP_TIME      DATE,IP_ADDRESS     VARCHAR2 (20),OBJECT_OWNER   VARCHAR2 (30),OBJECT_NAME    VARCHAR2 (30),OBJECT_TYPE    VARCHAR2 (20),DROP_BY_USER   VARCHAR2 (30)
);

(2) 创建删除表操作的触发器

CREATE OR REPLACE TRIGGER DROP_INFO
AFTER DROP ON username.schema
BEGIN
INSERT INTO DROP_LOG
(SESSION_ID,
DROP_TIME,
IP_ADDRESS,
OBJECT_OWNER,
OBJECT_NAME,
OBJECT_TYPE,
DROP_BY_USER)
VALUES(userenv('sessionid'),
SYSDATE,
sys_context('userenv','ip_address'),
SYS.DICTIONARY_OBJ_OWNER,
SYS.DICTIONARY_OBJ_NAME,
SYS.DICTIONARY_OBJ_TYPE,
SYS.LOGIN_USER);
end;
/

方案二,开启库audit审计记录登录功能

Oracle的审计功能(Audit)用于监视用户所执行的数据库操作,审计记录可存在数据字典表(称为审计记录:存储在SYSTEM表空间中的sys.aud$表中,可通过视图dba_audit_trail查看)或操作系统审计记录中(默认位置为$ORACLE_BASE/admin/$ORACLE_SID/adump/),默认情况下审计是不开启。

和审计相关的两个参数说明,

参数1:audit_sys_operations

默认为false,当设置为true时,所有sys用户(包括以sysdba、sysoper身份登录的用户)的操作都会被记录,audit trail不会写在aud$表中,Linux/Unix平台中则会记录在audit_file_dest参数指定的文件中。

参数2:audit_trail

None:是默认值,不做任何审计。

DB:审计的结果只有连接信息,记录在数据库的审计表aud$。

DB,Extended:这样审计结果里面除了连接信息还包含了当时执行的具体语句。

OS:将audit trail 记录在操作系统文件中,文件名由参数audit_file_dest指定位置。

XML:10g里新增的。

注意:上述两个参数是static参数,需重启数据库方可生效。

(1) 检查审计功能是否开启

SQLPLUS> connect / AS SYSDBA
SQLPLUS> select * from sys.aud$; --没有记录返回
SQLPLUS> select * from dba_audit_trail; - 没有记录返回

如上述查询发现表不存在,说明审计相关的表还没有安装,需要安装。安装方式如下,

SQLPLUS> connect / as sysdba
SQLPLUS> @$ORACLE_HOME/rdbms/admin/cataudit.sql

注意:审计表默认安装在SYSTEM表空间,所以要确保SYSTEM表空间充足。

(2) 开启审计功能

设置审计参数

SQL> alter system set audit_trail=db scope=spfile;

如果要审计管理用户(以sysdba/sysoper角色登陆),需要开此参数,

SQL> alter system set audit_sys_operations=TRUE scope=spfile;

重新启动数据库。

(3) 以SYSTEM帐号登录数据库执行下列语句,设置CONNECT审计并检查是否设置成功:

SQL> connect system/password
--审计登陆用户
SQL> audit connect

如下是常用的几个审计举例,

-- 审计所有对表的操作
SQL> audit all on table;-- 审计用户test对表的所有操作
sql> audit table by test;-- 审计任何用户删除用户test表的操作
SQL> AUDIT DELETE ANY test.TABLE;-- 审计任何用户删除失败的情况
SQL> AUDIT DELETE ANY TABLE WHENEVER NOT SUCCESSFUL;-- 只审计删除成功的情况
SQL> AUDIT DELETE ANY TABLE WHENEVER SUCCESSFUL;-- 审计SYSTEM用户对表user.table的delete,update,insert操作
SQL> AUDIT DELETE,UPDATE,INSERT ON user.table by SYSTEM;

以SYSTEM帐号登录数据库执行下列语句,设置CONNECT审计并检查是否设置成功,

SQL> col user_name format a20
SQL> col audit_option format a20
SQL> set linesize 999
SQL> select user_name, audit_option, success, failure from sys.dba_stmt_audit_opts;
USER_NAME   AUDIT_OPTION         SUCCESS                        FAILURE
----------- -------------------- ------------------------------ ------------------------------ALTER SYSTEM         BY ACCESS                      BY ACCESSSYSTEM AUDIT         BY ACCESS                      BY ACCESSCREATE SESSION       BY ACCESS                      BY ACCESSCREATE USER          BY ACCESS                      BY ACCESSALTER USER           BY ACCESS                      BY ACCESSDROP USER            BY ACCESS                      BY ACCESSPUBLIC SYNONYM       BY ACCESS                      BY ACCESSDATABASE LINK        BY ACCESS                      BY ACCESSROLE                 BY ACCESS                      BY ACCESSPROFILE              BY ACCESS                      BY ACCESSCREATE ANY TABLE     BY ACCESS                      BY ACCESS

(4) 查询aud$表就可以查看到审计结果了,

SQL> select sessionid, to_char(timestamp#,'DD-MON-YY:HH24:MI:SS') \
login,userid, to_char(logoff$time,'DD-MON-YY:HH24:MI:SS') logoff \
from sys.aud$ where userid='USERNAME';

(5) 关闭审计的方法,直接在审计语句前加no,例如,

SQL> noaudit connect
Sql> noaudit all on t_test;

另外,请注意aud$表等审计相关的表存放在SYSTEM表空间,为了不影响系统性能,保护SYSTEM表空间不被占用,最好将aud$移动到其他的表空间上,可使用下面语句执行移动表空间的操作,

sql> connect / as sysdba;
sql> alter table aud$ move tablespace <new tablespace>;
sql> alter index I_aud1 rebuild online tablespace <new tablespace>;
SQL> alter table audit$ move tablespace <new tablespace>;
SQL> alter index i_audit rebuild online tablespace <new tablespace>;
SQL> alter table audit_actions move tablespace <new tablespace>;
SQL> alter index i_audit_actions rebuild online tablespace <new tablespace>;

方法三,使用logmnr进行挖取日志分析

操作步骤如下:

(1) sys用户登陆,安装logmnr工具

SQL>@$ORACLE_HOME\rdbms\admin\dbmslm.sql;
SQL>@ $ORACLE_HOME\rdbms\admin\dbmslmd.sql;

脚本1用来创建DBMS_LOGMNR包,该包用来分析日志文件。

脚本2用来创建DBMS_LOGMNR_D包,该包用来创建数据字典文件。

(2) 修改初始参数文件

UTL_FILE_DIR = ($ORACLE_HOME\logs)

重新启动数据库,使新加的参数生效。

(3) 创建数据字典文件

SQL> connect /as sysdbaSQL> execute dbms_logmnr_d.build(dictionary_filename => 'dict.ora',dictionary_location => '/oracle/logs');

(4) 创建分析列表,添加分析日志

SQL> execute dbms_logmnr.add_logfile(LogFileName => '/ORACLE/ORADATA/ORADBSP/REDO01.LOG',Options => dbms_logmnr.new);

(5) 添加分析日志(建议一次添加1个)

SQL> execute dbms_logmnr.add_logfile(LogFileName => '/ORACLE/ORADATA/ORADBSP/REDO02.LOG',Options => dbms_logmnr.ADDFILE);

(6) logmnr日志分析

无限制条件
SQL> execute dbms_logmnr.start_logmnr(DictFileName => '/oracle/logs'dict.ora'); 带限制条件
基于时间段的分析
SQL> execute dbms_logmnr.start_logmnr(startTime => to_date('20191112100000','yyyy-mm-dd hh24:mi:ss'),endTime => to_date('20191112110000','yyyy-mm-dd hh24:mi:ss'),DictFileName => '/oracle/logs'dict.ora');

(7) 分析后释放内存

SQL> execute dbms_logmnr.end_logmnr;

(8) 删除日志分析文件

SQL> exec dbms_logmnr.add_logfile('/ORACLE/ORADATA/ORADBSP/REDO02.LOG',dbms_logmnr.removefile);

(9) 查看logmnr工具分析结果

-- 所有与logmnr相关的视图
SQL> select * from dict t where t.table_name like '%LOGMNR%';

上述语句中,分析结果存在GV$LOGMNR_LOGS 分析日志列表视图,使用如下语句查询,

SQL> create table logmnr_tmp as select * from GV$GV$LOGMNR_LOGS;
SQL>SELECT scn,timestamp,log_id,seg_owner,seg_type,table_space,data_blk#,data_obj#,data_objd#,session#,serial#,username,session_info,sql_redo,sql_undoFROM logmnr_tmp tWHERE t.sql_redo LIKE 'delete%';

logmnr具体操作可参考《误操作怎么办?试试这个神器-LogMiner》。

以上就是这三种审计功能的方案,可以说各有千秋,

(1) trigger触发器的方案,实现简单,但触发器并不很推荐,一个是可能增加维护成本,另外就是因为这是同步的操作,会对正常业务的性能产生一些影响。

(2) Audit是Oracle自带支持的审计功能,术业有专攻,就是做这事儿的,因此无论从记录信息的粒度、全面性、准确性等方面,都是非常出众的。当然多做了事儿,肯定对性能有一定的开销,还是要根据需求场景,来决定是否开启审计功能。

(3) logmnr,相当于离线处理,因此对正常业务的侵入性肯定要小很多,但是不像前两个方案,数据都是实时存储的,即使是写脚本,都需要定期执行,解析日志。

因此,以上三种方案,都可以实现知道谁登陆Oracle数据库的需求,如果有其他需求,例如响应时间、并发量等,就可以结合实际的场景,选择更合适的方案。

近期更新的文章:

《技术负责人如何搞垮一个团队?》

《最近碰到的一些问题》

《Oracle MySQL开源许可种种争议的解惑》

《从专家的角度,了解一些国产数据库优化的心得》

《什么是数据库的根技术?》

文章分类和索引:

《公众号1000篇文章分类和索引》

Oracle中如何记录访问数据库的登录信息?相关推荐

  1. 【DB笔试面试713】在Oracle中,如何将一个数据库添加到CRS中?

    ♣ 题目部分 在Oracle中,如何将一个数据库添加到CRS中? ♣ 答案部分 虽然通过DBCA(DataBase Configuration Assistant,数据库配置助手)创建的数据库会自动加 ...

  2. 上传图片至服务器,写入到数据库Blob字段中,以及从数据库读取Blob信息(iframe父子页面传值)(1)

    最近做了个用户维护功能,涉及到照片的操作. 照片是存到数据库oracle中的Blob字段中. 难点有两个: 1,图片的上传:2,Blob字段的读取. 先说图片的上传吧, 我使用common-fileu ...

  3. 【DB笔试面试639】在Oracle中,什么是多列统计信息(Extended Statistics)?

    ♣ 题目部分 在Oracle中,什么是多列统计信息(Extended Statistics)? ♣ 答案部分 Oracle优化器对于基数值的估算是否准确关系到能否生成最优的执行计划,而基数值估算的准确 ...

  4. ORACLE 限制特定IP访问数据库 访问白名单

    限制指定机器IP访问oracle数据库 通过使用数据库服务器端的sqlnet.ora文件可以实现禁止指定IP主机访问数据库的功能,这对于提升数据库的安全性有很大的帮助,与此同时,这个技术为我们管理和约 ...

  5. .Net程序员学用Oracle系列(16):访问数据库(ODP.NET)

    1..Net for Oracle 常见数据库驱动 1.1.微软提供的驱动 1.2.甲骨文提供的驱动 1.3.其它厂商提供的驱动 2.ODP.NET 常见问题分析 2.1.参数化问题 2.2.方法调用 ...

  6. Python中通过cx_Oracle访问数据库遇到的问题总结

    以下是Python中通过cx_Oracle操作数据库的过程中我所遇到的问题总结,感谢我们测试组的前辈朱勃给予的帮助最终解决了下列两个问题: 1)安装cx_Oracle会遇到的问题:在Windows下安 ...

  7. Asp.Net MVC访问数据库实现登录

    原文链接https://blog.csdn.net/u013324517/article/details/40651151 原来一直不明白MVC项目是怎样访问数据库的,项目中也没有看到与ADO.NET ...

  8. Spring Boot中使用JdbcTemplate访问数据库

    本文介绍在Spring Boot基础下配置数据源和通过JdbcTemplate编写数据访问的示例. 数据源配置 在我们访问数据库的时候,需要先配置一个数据源,下面分别介绍一下几种不同的数据库配置方式. ...

  9. springboot几种注入_Spring Boot中使用JdbcTemplate访问数据库

    本文介绍在Spring Boot基础下配置数据源和通过JdbcTemplate编写数据访问的示例. 数据源配置 在我们访问数据库的时候,需要先配置一个数据源,下面分别介绍一下几种不同的数据库配置方式. ...

最新文章

  1. 实验4 [BX]和loop指令
  2. php nodejs 前台,NodeJS之前端注册页面
  3. halcon read_ocr_trainf 从文件中读取训练字符并转换为图像
  4. mysql 如何凭借几个列_我如何总结MySQL中的几个列
  5. 如何使用ReiBoot修复iOS系统
  6. [LeetCode]Linked List Cycle
  7. 2017/08/07 工作日志
  8. 罗技g502 g102游戏驱动ghub详细 教程
  9. 一文带你由浅入深Netty异步非阻塞世界
  10. STM32F4定时器介绍
  11. 【已解决】ocker: Error response from daemon: Conflict. The container name “/nginx“ is alrea.....
  12. java 获取meta-inf路径_【Java】WEB-INF目录与META-INF目录的作用
  13. 分布式之分布式事务、分布式锁、分布式Session
  14. 一周疫情对行业影响观察 | 对香港IPO冲击大于内地,纺织服装新增企业同比下滑超五成...
  15. t440p安装黑苹果+win10双系统记录
  16. MTK DTS 文件配置
  17. 疯狂的程序员(绝影)
  18. webservice开发调用
  19. 小提琴1234567位置图解_小提琴指法图233(免费)
  20. 【HDOJ】1021 Fibonacci Again_天涯浪子_新浪博客

热门文章

  1. 基层管理者的角色定位
  2. 这个5.10阿里日不一般!造(躁)起来~淘系的年轻人们!
  3. 学习这东西确实得稳扎稳打,勿焦勿躁
  4. 你用了几年,才达到50万年薪?
  5. winform datagridview控件设置列标题字体大小无效问题
  6. docker-compose up命令
  7. Comet OJ - 2019国庆欢乐赛(赛后整理)
  8. python 实现QQ群接龙统计未接龙成员名单
  9. selenium 接管已经打开的本地浏览器窗口
  10. 学一点Wi-Fi: CCMP