在上一篇文章中讨论了如何利用VPD对Oracle表中的行进行访问控制(见《[Oracle] 数据库安全之 - 虚拟私有数据库 (VPD)》),下面介绍一种比VPD复杂一点的访问控制技术——OLS (Oracle Label Security)。
如果你的数据库版本是10g,则需要额外安装OLS组件,但如果是11g,只要启用OLS即可,因为11g里OLS是默认安装的,下面是11g下启动OLS的语句:
C:\Users\xianzhu>chopt enable lbac Writing to C:/app/xianzhu/product/11.2.0/dbhome_1/install/enable_lbac.log... movefile C:\app\xianzhu\product\11.2.0\dbhome_1/bin/oralbac11.dll.dbl C:\app\xianzhu\product\11.2.0\dbhome_1/bin/oralbac11.dll
C:\Users\xianzhu>sqlplus test/test SQL*Plus: Release 11.2.0.1.0 Production on 星期日 6月 9 09:40:17 2013 Copyright (c) 1982, 2010, Oracle. All rights reserved. 连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production With the Partitioning, Oracle Label Security, OLAP, Data Mining and Real Application Testing options
1)如果你照以上步骤,正确启用OLS之后,Oracle会创建一个用户lbacsys,但是该用户是被锁的,首次使用需要解锁并修改密码:
SQL> alter user lbacsys account unlock; 用户已更改。 SQL> alter user lbacsys identified by lbacsys; 用户已更改。
SQL> conn lbacsys/lbacsys 已连接。 SQL> exec sa_sysdba.create_policy(policy_name => 'ACCESS_LOCATIONS', column_name => 'OLS_COLUMNE'); PL/SQL 过程已成功完成。 SQL> select policy_name, status from dba_sa_policies; POLICY_NAME STATUS ------------------------------ -------- ACCESS_LOCATIONS ENABLED
SQL> exec sa_components.create_level(policy_name=>'ACCESS_LOCATIONS',level_num=>1000,short_name=>'PUB',long_name=>'PUBLIC CITY'); PL/SQL 过程已成功完成。 SQL> exec sa_components.create_level(policy_name=>'ACCESS_LOCATIONS',level_num=>2000,short_name=>'CONF',long_name=>'CONFIDENTIAL CITY'); PL/SQL 过程已成功完成。 SQL> exec sa_components.create_level(policy_name=>'ACCESS_LOCATIONS',level_num=>3000,short_name=>'SENS',long_name=>'SENSITIVE CITY'); PL/SQL 过程已成功完成。 SQL> select * from dba_sa_levels order by level_num; POLICY_NAME LEVEL_NUM SHORT_NAME LONG_NAME -------------------- ---------- ---------- -------------------- ACCESS_LOCATIONS 1000 PUB PUBLIC CITY ACCESS_LOCATIONS 2000 CONF CONFIDENTIAL CITY ACCESS_LOCATIONS 3000 SENS SENSITIVE CITY
SQL> exec sa_label_admin.create_label(policy_name=>'ACCESS_LOCATIONS',label_tag=>'1000',label_value=>'PUB',data_label=>TRUE); PL/SQL 过程已成功完成。 SQL> exec sa_label_admin.create_label(policy_name=>'ACCESS_LOCATIONS',label_tag=>'2000',label_value=>'CONF',data_label=>TRUE); PL/SQL 过程已成功完成。 SQL> exec sa_label_admin.create_label(policy_name=>'ACCESS_LOCATIONS',label_tag=>'3000',label_value=>'SENS',data_label=>TRUE); PL/SQL 过程已成功完成。 SQL> exec sa_policy_admin.apply_table_policy(policy_name=>'ACCESS_LOCATIONS',schema_name=>'HR',table_name=>'LOCATIONS',table_options=>'LABEL_DEFAULT,READ_CONTROL'); PL/SQL 过程已成功完成。
SQL> create user tom identified by tom; 用户已创建。 SQL> create user peter identified by peter; 用户已创建。 SQL> create user rose identified by rose; 用户已创建。 SQL> grant connect to tom, peter, rose; 授权成功。 SQL> grant select on hr.locations to tom, peter, rose; 授权成功。
SQL> exec sa_user_admin.set_user_labels(policy_name=>'ACCESS_LOCATIONS',user_name=>'TOM',max_read_label=>'SENS'); PL/SQL 过程已成功完成。 SQL> exec sa_user_admin.set_user_labels(policy_name=>'ACCESS_LOCATIONS',user_name=>'PETER',max_read_label=>'CONF'); PL/SQL 过程已成功完成。 SQL> exec sa_user_admin.set_user_labels(policy_name=>'ACCESS_LOCATIONS',user_name=>'ROSE',max_read_label=>'PUB'); PL/SQL 过程已成功完成。
SQL> execute sa_user_admin.set_user_privs(policy_name=>'ACCESS_LOCATIONS',user_name=>'HR',privileges=>'FULL'); PL/SQL 过程已成功完成。 SQL> update hr.locations set ols_columne=CHAR_TO_LABEL('ACCESS_LOCATIONS','SENS') where upper(city) in ('BEIJING','TOKYO','SINGAPORE'); 已更新3行。 SQL> update hr.locations set ols_columne=CHAR_TO_LABEL('ACCESS_LOCATIONS','CONF') where upper(city) in ('MUNICH','OXFORD','ROME'); 已更新2行。 SQL> update hr.locations set ols_columne=CHAR_TO_LABEL('ACCESS_LOCATIONS','PUB') where ols_columne is null; 已更新18行。