在ORACLE中,RLS有时也叫做虚拟私有数据库(VPD)或者细粒度访问控制(FGAC)。
RLS由8i引进,利用这一特性我们可以对表定义安全策略(并且指明对表的操作类型),实现对用户可以看到或者修改的数据进行限制。
这个功能大部分通过内置包DBMS_RLS实现。下面通过一个实例说明,详细情况请查阅官方文档:
-----------------------------------------------------------------------------------------------------------------------------------
环境:11.2.0.1.0 - 64bit
实现效果:SCOTT下新建一张客户表和订单表:CUSTOMERS、orders_tab,实现客户表内用户登录只能看到自己的订单;
1、创建用户账户和示例表:
dba用户登录:
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_vpd IDENTIFIED BY password; GRANT EXECUTE ON DBMS_SESSION TO sysadmin_vpd; GRANT EXECUTE ON DBMS_RLS TO sysadmin_vpd;
GRANT CREATE SESSION TO tbrooke IDENTIFIED BY password; GRANT CREATE SESSION TO owoods IDENTIFIED BY password;
CONNECT scott Enter password: password CREATE TABLE customers ( cust_no NUMBER(4), cust_name VARCHAR2(20)); INSERT INTO customers VALUES (1234, 'TBROOKE'); INSERT INTO customers VALUES (5678, 'OWOODS');
GRANT SELECT ON customers TO sysadmin_vpd;
CREATE TABLE orders_tab ( cust_no NUMBER(4), order_no NUMBER(4)); INSERT INTO orders_tab VALUES (1234, 9876); INSERT INTO orders_tab VALUES (5678, 5432); INSERT INTO orders_tab VALUES (5678, 4592);
GRANT SELECT ON orders_tab TO tbrooke; GRANT SELECT ON orders_tab TO owoods;
2、创建基于会话的应用程序上下文:
CONNECT sysadmin_vpd Enter password: password
CREATE OR REPLACE CONTEXT orders_ctx USING orders_ctx_pkg;
CREATE OR REPLACE PACKAGE orders_ctx_pkg IS
PROCEDURE set_custnum;
END;
/
CREATE OR REPLACE PACKAGE BODY orders_ctx_pkg IS
PROCEDURE set_custnum
AS
custnum NUMBER;
BEGIN
SELECT cust_no INTO custnum FROM scott.customers
WHERE cust_name = SYS_CONTEXT('USERENV', 'SESSION_USER');
DBMS_SESSION.SET_CONTEXT('orders_ctx', 'cust_no', custnum);
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END set_custnum;
END;
/
3、创建登录触发器调用应用程序上下文包:
CREATE TRIGGER set_custno_ctx_trig AFTER LOGON ON DATABASE BEGIN sysadmin_vpd.orders_ctx_pkg.set_custnum; END; /4、创建策略函数(policy function):
CREATE OR REPLACE FUNCTION get_user_orders(
schema_p IN VARCHAR2,
table_p IN VARCHAR2)
RETURN VARCHAR2
AS
orders_pred VARCHAR2 (400);
BEGIN
orders_pred := 'cust_no = SYS_CONTEXT(''orders_ctx'', ''cust_no'')';
RETURN orders_pred;
END;
/
5、创建安全策略(security policy):
BEGIN DBMS_RLS.ADD_POLICY ( object_schema => 'scott', object_name => 'orders_tab', policy_name => 'orders_policy', function_schema => 'sysadmin_vpd', policy_function => 'get_user_orders', statement_types => 'select'); END; /6、测试安全策略:
CONNECT tbrooke Enter password: password
SELECT * FROM scott.orders_tab;
The following output should appear:
CUST_NO ORDER_NO
---------- ----------
1234 9876
CONNECT owoods Enter password: passwords SELECT * FROM scott.orders_tab
The following output should appear:
CUST_NO ORDER_NO
---------- ----------
5678 5432
5678 4592
7、移除示例组件:
Connect as user OE and remove the orders_tab and customers tables.
CONNNECT SCOTT Enter password: password DROP TABLE orders_tab; DROP TABLE customers;
Connect as user SYS, connecting with AS SYSDBA.
CONNECT sys/as sysdba Enter password: password
Run the following statements to drop the components for this tutorial:
DROP CONTEXT