博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用Oracle VPD实现行级安全保护(一)
阅读量:6378 次
发布时间:2019-06-23

本文共 2708 字,大约阅读时间需要 9 分钟。

大家都知道,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,如需转载请自行联系原作者

你可能感兴趣的文章
【Android自定义View】绘图之文字篇(三)
查看>>
适配iOS 11和iPhoneX屏幕适配遇到的一些坑
查看>>
Fetch API 简单封装
查看>>
给媳妇做一个记录心情的小程序
查看>>
iOS App无需跳转系统设置自动连接Wi-Fi
查看>>
一道柯里化面试题
查看>>
本科studying abroad 无法毕业申请硕士转学转校处理一切studying abroad 问题
查看>>
RxJava(RxAndroid)的简单学习
查看>>
Java8 函数式编程之函数接口(下)
查看>>
【本人秃顶程序员】MySQL 全表 COUNT(*) 简述
查看>>
centos7中使用febootstrap自制一个基础的centos 7.2的docker镜像
查看>>
系统优化和克隆过程
查看>>
C#开发Unity游戏教程之判断语句
查看>>
Windows自带Android模拟器启动失败
查看>>
安装 SharePoint Server 2007
查看>>
springmvc mybatis 调用sql , 转成json
查看>>
linux centos 7 网卡突然不能上网异常解决
查看>>
shell+Python实现简单的链路监控
查看>>
授之以渔-运维平台发布模块一(Jenkins篇)
查看>>
DedeCMS操作基础(一)
查看>>