利用Oracle VPD实现行级安全保护(一)

简介:
大家都知道,Oracle的锁机制是行级别的,下面来看看Oracle的安全访问机制:
安全的数据过滤,必须在基础数据表的一层就完成,这样用户无论是通过视图还是基础表都无法绕过安全控制。而VPD(virtual private database)最根本的能力就是“会透明的过滤数据”,提供行级安全保护。

Oracle8i以后的版本都提供了VPD这样一个强大的功能来实现呼声日益增高的系统安全性要求。通过设置基于VPD的细粒度访问策略,我们可以只通过DBA的工作(不需要修改应用,也就是应用透明化)就可以实现用户只能访问自己有权限访问的数据,当然如果需要更加复杂的权限控制开发人员的参与还是必不可少的。

下面用一个简单的例子来实现这样的功能,在EMP表中的用户登录数据库以后只能查询和更新自己所属部门的其它员工资料,不是本部门的不会显示也不允许更新。
————————————————————————————————————————————————————
1.我们需要两个用户,一个是用于设置VPD策略的hr用户,另外一个是在hr.employees表中有记录的David用户
SQL> create user David identified by boylook;

User created.

SQL> grant create session to david;

Grant succeeded.

SQL> conn hr
Enter password: 
Connected.

2.首先用hr用户创建策略权限表。为方便起见我们直接通过employees表创建,本策略表中包含了员工姓名和所属部门编号。其中David用户同时属于60和80这两个部门。
SQL> create table rls_test as select * from employees;

Table created.

SQL> select department_id from employees where first_name = 'David';

DEPARTMENT_ID
-------------
60
80
80

3.hr用户创建VPD策略需要的函数
SQL> @create_vpd_func(见文章结尾)

Function created.
该函数实现以下功能:
如果使用hr用户登录,因为表是属于该用户的,所以不加任何限制。
如果使用其它用户登录(SYS用户不受此限制),那么根据employees表中该用户的所属部门决定哪些记录允许该用户操作,本例中60和80这两个部门的员工David用户将都能看见。
如果登录的用户不在employees表中,那么该用户查看不到任何数据。

注意:
VPD策略函数必须包含两个参数,本例中是p_schema和p_table,即使这两个参数在函数中没有用到,也必须包含。否则在后面检索EMP表数据的时候将会报:
PLS-00306: 调用 'GET_USER_DEPT_ID' 时参数个数或类型错误。

4.用hr用户创建VPD策略
SQL> conn / as sysdba
Connected.
SQL> grant execute on dbms_rls to hr
2 ;

Grant succeeded.

SQL> conn hr
Enter password: 
Connected.
SQL> @test_add_policy;
10 /

PL/SQL procedure successfully completed.

5.至此为止我们的VPD方案就已经设置完毕了。下面我们测试一下 --hr用户可以选择出全部的107条记录
SQL> select count(*) from employees;

COUNT(*)
----------
107

SQL> conn david
Enter password: 
Connected.
--David用户只能选出属于部门60,80的39条记录SQL> select count(*) from hr.employees;

COUNT(*)
----------
39

附:
cat create_vpd_func.sql 
create or replace function test_vpd(p_schema in varchar2,p_object in varchar2)
return varchar2
as
l_retstr varchar2(2000);

type dept_id_type is table of employees.department_id%type;

dept_id_tab dept_id_type;

temp_v varchar2(2000);
begin
if sys_context('userenv','current_user') = user then 
return '';
end if;
select department_id
bulk collect into dept_id_tab
from rls_test
where upper(first_name) = sys_context('userenv','session_user');

if dept_id_tab.count = 0 then
l_retstr := '1=2';
else
for i in dept_id_tab.first..dept_id_tab.last
loop
temp_v := temp_v||','||dept_id_tab(i);
end loop;
l_retstr := 'department_id in('||ltrim(temp_v,',')||')';
end if; 
return l_retstr;
end;
/
cat test_add_policy.sql 
declare
begin
dbms_rls.add_policy(
object_schema =>'HR',
object_name =>'EMPLOYEES',
policy_name =>'HIDE_EMP',
function_schema =>'HR',
policy_function =>'TEST_VPD');

end;



本文转自MIKE老毕 51CTO博客,原文链接:http://blog.51cto.com/boylook/1298619,如需转载请自行联系原作者


相关文章
|
存储 SQL Oracle
Oracle使用expdp/impdp实现全库导入导出的整体流程
Oracle的全库导入,首先一点必须先创建数据库,创建了数据库,才能往该数据库导入所有数据。相对来说,使用Oracle进行数据导入导出还很有些“麻烦”的,大多数资料上来就是......
6122 0
Oracle使用expdp/impdp实现全库导入导出的整体流程
|
存储 设计模式 Oracle
Oracle跨数据库实现定时同步指定表中的数据
Oracle跨数据库实现定时同步指定表中的数据
|
Oracle 关系型数据库
查询Oracle字段列的最大值并查询多列数据的实现方法
查询Oracle字段列的最大值并查询多列数据的实现方法
2093 0
|
存储 SQL Oracle
跨Oracle数据库实现表级别的实时同步
跨Oracle数据库实现表级别的实时同步
|
供应链 安全 Oracle
Oracle 4月安全通告
Oracle 4月安全通告
|
Oracle Java 关系型数据库
oracle实现主键自增长及自动生成策略
oracle实现主键自增长及自动生成策略
473 0
|
SQL Oracle 关系型数据库
SpringBoot整合oceanbase,实现oracle无缝切换到oceanbase
随着去“IOE”化的潮流,近些年来,许多与国家相关的项目不约而同到地往”国产化“方向靠拢,不可避免地,一些项目可能需要进行数据库迁移。
975 0
SpringBoot整合oceanbase,实现oracle无缝切换到oceanbase
|
Oracle 安全 关系型数据库
Oracle学习(十四):管理用户安全
本文主要讲Oracle管理用户安全
108 0
Oracle学习(十四):管理用户安全
|
Oracle 关系型数据库 数据库
Oracle数据库访问其他用户下的表,不加表所属的用户名的实现方法
Oracle数据库访问其他用户下的表,不加表所属的用户名的实现方法

推荐镜像

更多