oracle数据库中的虚拟表,Oracle10g中的虚拟专用数据库(VPD)

什么是VPD

所谓虚拟专用数据库(VPD)指的是,通过在数据库里进行配置,从而让不同的用户只能查看某个表里的部分数据。VPD分为以下两个级别:

行级别:在该级别下,可以控制某些用户只能查看到某些行数据。例如对于销售数据表来说,每一名销售人员仅仅能检索自己的销售数据,而不能检索其他用户的销售数据。

列级别:在该级别下,可以控制某些用户不能检索某些列的数据。例如HR用户下的EMPLOYEES表,包含salary这一个列,表示工资。由于该列不允许任何用户都可以看到,所以可以在这个列上使用一些设置,这样其他一些用户查看这一列信息时,其数值均为NULL。

利用Oracle的细粒度访问控制,可用一种非常复杂的方式调整安全策略,可将细粒度访问控制用于以下目的:

l 通过SELECT、INSERT、UPDATE、DELETE语句实施行访问控制

l 建立一个安全策略,它基于某个列的特定值控制访问

l 创建与查询执行中动态更改策略相同的方式使用的策略

l 创建一组安全策略,成为策略组

基于行的VPD

基于行的VPD也叫做Fine-Grained Access Control,即FGAC。FGAC通过定义规则来实现,规则的集合叫做FGAC政策(Policy)。如果对某个表设置了FGAC,则当用户对该表发出查询或者DML语句时,Oracle都会根据定义的FGAC政策,而自动改写这些SQL语句。其改写方式为自动在SQL语句后面添加where条件。

使用FGAC策略来限定返回记录的方式具有很多优点。例如:不需要改写应用程序,对用户完全透明,集中设置,便于管理等。

在使用FGAC时,会涉及到应用程序上下文(Application

Context)的概念,使用应用程序上下文可以简化FGAC管理的实现。应用程序上下文是一个数据库对象,可以把它理解为数据库里的每一个session的全局环境变量。一旦用户登录到数据库,从而创建出session以后,应用程序上下文就在整个session的生命周期里可用。在应用程序上下文里可以定义多个属性,并为这些属性设置具体的值。而用户不能直接修改属性的值,只能通过程序包来修改属性值。应用程序上下文总是有用户SYS拥有的。

例如:对于用户HR的EMPLOYEES表而言,我们可以创建一个应用程序上下文,当用户登录时,将该用户的ID号作为一个属性值放入该应用程序上下文中。然后再定义FGAC政策的时候,将该用户ID号取出,并作为限定条件短语返回给Oracle,从而实现FGAC。

在Oracle数据库中,已经为每一个session都预先建立了一个应用程序上下文:userenv。

查看方法,通过下面的查询可以看到:

select

sys_context('userenv','ip_address') as

"IP",sys_context('userenv','db_name') as "DB" from dual

SQL>

select sys_context('userenv','terminal') as "application ctx" from

dual;

application

ctx

--------------------------------------------------------------------------------

646C3C9C9D8E4DA

下表列出了USERENV命名空间中常用的预定义属性

属性

说明

Instance

实例ID

Entryid

审计条目标识

Current_user

启动会话的用户名称

Session_user

数据库用户名,当前用户通过它进行认证

Proxy_user

为会话用户打开一个会话的中间层次名称

Db_name

数据库名称

Host

数据库在其上运行的主机名

Os_user

操作系统帐号名

Terminal

用来访问数据库的客户机终端

Ip_address

客户机的IP地址

External_name

数据库用户的外部名称

在用户登录时,识别用户的类型和获得关键的用户属性非常重要,以后可将这些信息用于附加到数据库对象的安全策略中,将内建的USERENV命名空间用来获得这些信息是很理想的。

USERENV命名空间仅是可用的应用环境命名空间之一。你还必须创建自己的应用环境,以便能够规定在设置自己的安全策略时需要使用哪些属性。为了定义自己的应用环境,还需要做以下工作:

(1)创建一个利用各种函数的帮助设置环境的PLSQL程序包

(2)创建一个使用所创建的程序包的应用环境。

l 创建设置环境的程序包

如果要为用户hr设置应用环境,需要创建一个PLSQL程序包。

下面的代码说明如何创建一个名为HR_CONTEXT的设置应用环境的简单程序包。此程序包包含一个过程,它选择employee_id列的值到empnum变量。因为这条SELECT语句基于一条WHERE子句根据SESSION_USER属性确定雇员的last_namae,所以此employee_id将是数据库用来认证当前用户的用户名的employee_id。:

SQL> conn hr/hr;

已连接。

create or replace

package hr_context is

-- Author : BURKE

-- Created : 2008-4-26 17:02:34

-- Purpose :

procedure select_emp_no;

end hr_context;

create or replace package

body hr_context is

procedure select_emp_no is

empnum number;

begin

select employee_id into empnum from employees where

upper(last_name)=sys_context('USERENV','SESSION_USER');

dbms_session.set_context('employee_info','emp_num',empnum);

end select_emp_no;

end hr_context;

l 创建应用环境

一旦创建了帮助设置应用环境的程序包(HR_CONTEXT),则可以如下创建应用环境本身。请注意,hr用户使用前一节创建的程序包创建employee_info应用环境。

connect system/sysadmin@burke as sysdba;

grant create any context

to hr;

conn hr/hr;

CREATE

CONTEXT employee_info USING hr.context;

SQL> CREATE

CONTEXT employee_info USING hr.context;

上下文已创建。

可以用两种方法设置一个用户的应用环境。第一种方法是通过它自身实现一个应用环境,没有FGA的访问控制。为完成此工作,创建一个用户登录时的事件触发器,这样用户在登录数据库时将调用属于HR_CONTEXT程序包的SELECT_EMP_ON过程。

Conn

system/sysadmin@burke as sysdba;

create or replace

trigger hr.security_context

after logon on

database

declare

-- local variables

here

begin

hr_context.select_emp_no;

end security_context;

通过登录触发器使用了程序包的过程,它用来获取用户的employee_id并存储到emp_num变量。

第二种设置或引用应用环境的方法是利用VPD的完成成分,它使用一个策略函数来实现FGA的访问控制。

实现FGA的访问控制

在一些场合下,我们可能想限制某些用户对应用程序数据的访问。当然,可以通过视图来达到这一目的,但管理视图也会带来一些问题。如维护和审计等问题。

FGA允许限制Oracle用户,使得他们只能使用你让他们访问和修改的数据。使用策略函数(policy

function)有助于FGAC,策略函数附加到想要保护的表或者视图上。它使用动态可修改的语句将用户约束或者限制在表、视图或同义词的某些部分中。在分析用户的SQL语句时,FGAC让Oracle自动估计策略函数(一个表可以附加不止一个策略)。Oracle将在动态修改查询(如果有必要)后执行它。

注解:FGAC允许实现细颗粒度数据安全,使用这个特性,可实施行级安全策略。

FGAC涉及以下步骤:

(1)创建给用户的DML语句动态增加一个谓词的策略函数。谓词是基于某个操作符的WHERE子句。

Cust_no=(

Select custno from orders

whre

custname=SYS_CONTEXT(‘USERENV’,’SESSION_USER’)

)

实现安全策略的程序包将动态的附加一个词到ORDERS表上的所有SELECT语句中,只返回与该用户的客户名(cust_no)有关的那些订单。

(2)用户输入下面这样一条语句:

SELECT * FROM

ORDERS;

(3) Oracle将使用你创建的策略函数动态修改用户的语句。例如步骤2中的语句将被步骤1中的策略函数修改如下:

select * from orders where custno=(

select custno from customers

where custname=SYS_context('USERENV','SESSION_USER')

)

(4)

Oracle使用SYS_context('USERENV','SESSION_USER')返回的用户名对原查询进行修改,从而限制从ORDERS表返回的数据仅为该用户的数据。

创建hr_security程序包

create or replace

package HR_SECURITY is

-- Author : BURKE

-- Created : 2008-4-26 18:23:47

-- Purpose :

function empnum_sec(a1 varchar2,a2 varchar2)return

varchar2;

end HR_SECURITY;

create or replace package

body HR_SECURITY is

function empnum_sec(a1 varchar2,a2 varchar2)return

varchar2

is

d_predicate varchar2(2000);

begin

d_predicate:='employee_id=SYS_CONTEXT("EMPLOYEE_INFO","EMP_NUM")';

RETURN d_predicate;

end;

end HR_SECURITY;

上面的程序包hr_security将使用employee_info环境获取emp_num变量。

HR_SECURITY包中的d_predicate谓词指出,这种变换应该用于其employee_id与从employee_info环境取得的emp_num变量想匹配的任何雇员的查询。例如:如果用户salapati发布下面的命令:

select * from employees;

它将被我们的谓词修改为:

select * from employees

where employee_id=SYS_CONTEXT("EMPLOYEE_INFO","EMP_NUM");

创建安全策略

前一小节创建的程序包附加了一个动态谓词到某些SQL语句,这些SQL语句是employee_id与用employee_info应用环境导出的emp_num想匹配的雇员使用的。但是,我们仍然没有给EMPLOYEES表附加安全策略。也就是说,我们现在必须准确地指出HR_SECURITY程序包将应用于何种SQL语句,什么样的表。

在Oracle10gR2版本中,可以使用dbms_pls.add_policy过程为POLICY_TYPE参数指定以下5种类型的安全策略:

l 动态

l 静态

l 共享静态

l 环境敏感

l 共享环境敏感

(----.静态策略类型

对于静态策略类型,我们可以将参数POLICY_TYPE的值指定为DBMS_RLS.STATIC。在静态的策略类

型中,谓词在不同运行环境下都是相同的。静态策略函数运行一次,并且被缓存到SGA,这样静态策略

函数就非常快。访问相同对象的语句不需要重复运行策略函数,当然根据SYS_CONTEXT和SYSDATE

这样的属性不同,每次运行也可以产生不同的结果。 ----.共享-静态策略类型

当一个函数用于多个策略中的时候,我们称之为共享策略。共享策略可以在多个对象的业务处理策略相

同的时候,不必为每个对象都创建一个策略函数。我们应该将POLICY_TYPE设置为

DBMS_RLS.SHARED_STATIC。它的处理方式与STATIC相同。

----环境敏感策略

我们需要将参数POLICY_TYPE的值指定为DBMS_RLS.CONTEXT_SENSITIVE。如果数据库发现自上

次使用以后,运行的上下文环境发生了变化,那么就会对上下文敏感策略函数重新求值。

----共享-环境敏感策略类型

与环境敏感策略类似,只不过函数是可以共享的。我们需要将POLICY_TYPE指定为

DBMS_RLS.SHARED_CONTEXT_SENSTIVE。)

BEGIN

DBMS_RLS.ADD_POLICY(

object_schema=>'hr',

object_name=>'employees',

policy_name=>'manager_policy',

function_schema=>'hr',

policy_function=>'hr_security.empnum_sec',

statement_types=>'select'

);

END;

可以通过下面的查询验证新策略是否确实已经成功创建:

select object_name,policy_name,sel,ins,upd,del,enable from all_policies;

SQL>

select object_name,policy_name,sel,ins,upd,del,enable

2 from all_policies;

OBJECT_NAME POLICY_NAME SEL INS UPD DEL ENA

------------------------------

------------------------------ --- --- --- --- ---

EMPLOYEES MANAGER_POLICY YES NO NO NO YES

删除策略

begin

dbms_rls.drop_policy(

object_schema=>'hr',

object_name=>'employees',

policy_name=>'manager_policy'

);

end;

查询结果表明针对EMPLOYEES表的所有select语句现在由MANAGER_POLICY安全策略控制。

为使公众可以访问安全策略函数,以便所有访问数据库的用户能够使用它,可进行下面的授权

SQL>

grant execute on hr_security to public;

授权成功。

基于列的VPD

我们已经看到如何在访问表时实施行级安全策略。Oracle还允许使用列级VPD,在一个查询引用某个列或某些列时实现列级安全。列级VPD可以应用于表和视图。

创建列级安全策略与创建普通的安全策略几乎是相同的,只需在DBMS_RLS.ADD_POLICY过程中添加SEC_RELEVANT_COLS参数指出与安全相关的列即可。下面示例指出如何使用DMBS_RLS.ADD_POLICY过程创建一个列级安全策略。

BEGIN

DBMS_RLS.ADD_POLICY(

object_schema=>'hr',

object_name=>'employees',

policy_name=>'manager_policy',

function_schema=>'hr',

policy_function=>'hr_security.empnum_sec',

statement_types=>'select,insert',

sec_relevant_cols=>'salary'

);

END;

上面的例子中创建的列级安全策略仅仅在访问EMPLOYEE表的SALARY列时起作用。假如某个用户随后发出下面的查询:

Select

fname,lname,salary from employees;

列级VPD策略在查询中将通过列的安全策略转换SQL语句为:

select fname,lname,salary from employees

where salary='my_salary';

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值