原创 转载请注明出处
VPD 虚拟专用数据库,主要用来控制某个用户对特定列的一个访问权限,比如我是李三,我在查看员工信息表的时候,只要查看了薪水列,就只显示我李三的这一行,因为其他员工的薪水对我是保密了。使用包dbms_rls来管理列:只要用户查看了薪水列只返回这个用户相关的列。
1、表结构如下: SQL> select * from pp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH CLERK 7902 1980-12-17 6000.00 20
7499 ALLEN SALESMAN 7698 1981-2-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-2-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-4-2 2975.00 20
7654 MARTIN SALESMAN 7698 1981-9-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-5-1 2850.00 30
7782 CLARK MANAGER 7839 1981-6-9 2450.00 10
7788 SCOTT ANALYST 7566 1987-4-19 3000.00 20
7839 KING PRESIDENT 1981-11-17 5000.00 10
7844 TURNER SALESMAN 7698 1981-9-8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-5-23 1100.00 20
7900 JAMES CLERK 7698 1981-12-3 950.00 30
7902 FORD ANALYST 7566 1981-12-3 3000.00 20
7934 MILLER CLERK 7782 1982-1-23 1300.00 10
2、建立函数
create or replace function emp_pf
(owner varchar2,objname varchar2)
return varchar2
is
where_clause varchar2(2000);
begin
where_clause:='ename=sys_context(''userenv'',''session_user'')';
return where_clause;
end;
Function created 这个函数主要返回是当前会话的用户名,用于判断他一旦访问了薪水列,哪一列他能够查看。
3、建立策略
SQL> begin
2 dbms_rls.add_policy(object_name => 'pp',policy_name => 'TEST',function_schema => 'pp',policy_function => 'emp_pf',sec_relevant_cols => 'SAL',sec_relevant_cols_opt => dbms_rls.all_rows);
3 end;
4 /
4、登陆SMITH用户查看,可以看到这里的SAL列除了SMITH用户自己的SAL是有值的其他都是NULL,当然我这里使用了dbms_rls.all_rows显示所有列,策略列其他值放回为NULL。也可以不使用那样的话只会返回1列就是SAL有值的那一列。
SQL> select * from pp.pp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- ---------- --------- ------
7369 SMITH CLERK 7902 1980-12-17 6000 20
7499 ALLEN SALESMAN 7698 1981-2-20 300.00 30
7521 WARD SALESMAN 7698 1981-2-22 500.00 30
7566 JONES MANAGER 7839 1981-4-2 20
7654 MARTIN SALESMAN 7698 1981-9-28 1400.00 30
7698 BLAKE MANAGER 7839 1981-5-1 30
7782 CLARK MANAGER 7839 1981-6-9 10
7788 SCOTT ANALYST 7566 1987-4-19 20
7839 KING PRESIDENT 1981-11-17 10
7844 TURNER SALESMAN 7698 1981-9-8 0.00 30
7876 ADAMS CLERK 7788 1987-5-23 20
7900 JAMES CLERK 7698 1981-12-3 30
7902 FORD ANALYST 7566 1981-12-3 20
7934 MILLER CLERK 7782 1982-1-23 10
5、删除
SQL> execute dbms_rls.drop_policy(object_name => 'pp',policy_name=> 'TEST');
ORACLE 10G中VPD的策略因为要消耗较多的资源,所以引入了SGA缓存,所以有了5中不同类型的策略
1、动态
2、静态
3、共享-静态
4、上下文敏感
5、共享-上下文敏感
本人也不太熟悉,所以这里提一下。需要的朋友自己研究下。
FGA 细粒度审计,ORACLE其实提供了审计功能,但是为了支持更加复杂的审计情况引入了FGA,比如我只想审计谁修改了员工信息表中的薪水列,就可以考虑使用FGA来实现。使用包dbms_fga来管理列,我想审计PP表中对薪水列有关的且薪水列大于5000的SELECT UPDATE会话信息
1、查看表结构
SQL> select * from pp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH CLERK 7902 1980-12-17 6000.00 20
7499 ALLEN SALESMAN 7698 1981-2-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-2-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-4-2 2975.00 20
7654 MARTIN SALESMAN 7698 1981-9-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-5-1 2850.00 30
7782 CLARK MANAGER 7839 1981-6-9 2450.00 10
7788 SCOTT ANALYST 7566 1987-4-19 3000.00 20
7839 KING PRESIDENT 1981-11-17 5000.00 10
7844 TURNER SALESMAN 7698 1981-9-8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-5-23 1100.00 20
7900 JAMES CLERK 7698 1981-12-3 950.00 30
7902 FORD ANALYST 7566 1981-12-3 3000.00 20
7934 MILLER CLERK 7782 1982-1-23 1300.00 10
2、建立策略
execute dbms_fga.add_policy(policy_name => 'FGA_TEST',object_name => 'PP',audit_column=> 'SAL',statement_types=> 'SELECT,UPDATE',audit_condition => 'SAL>5000');
3、查看结果
SQL> select count(*) from pp where sal>5000;
COUNT(*)
----------
0
SQL> select count(*) from dba_fga_audit_trail;
COUNT(*)
----------
0
没有涉及到大于5000的现在进行UPDATE,SELECT
SQL> update pp set SAL=6000 where ENAME='SMITH';
1 row updated
SQL> commit;
Commit complete
SQL> select * from pp where ENAME='SMITH';
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH CLERK 7902 1980-12-17 6000.00 20
再次查看结果
SQL> select count(*) from dba_fga_audit_trail;
COUNT(*)
----------
2
SQL> select SESSION_ID,DB_USER,OS_USER,SQL_TEXT from dba_fga_audit_trail;
SESSION_ID DB_USER OS_USER SQL_TEXT
---------- ------------------------------ -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
68491 PP gaopeng
update pp set SAL=6000 where ENAME='SMITH'
68491 PP gaopeng
select * from pp where ENAME='SMITH'
不错吧。其实有时候还是很有用的,当然这两个包的选项都很多,我没学习完。这里只是给出了一些列子。