达梦虚拟专用数据库(VPD)技术

一、VPD概述
在某些系统中,权限控制必须定义到数据行访问权限的控制,此需求一般出现在同一系统中,不同的相对独立机构使用的情况。
比如,集团下属多个子公司,所有子公司使用同一套数据表,但不同子公司的数据相对隔离,也就是每个子公司的人员只能查看、操作本公司的数据。面对这种情况,绝大多数人会选择在表或视图加上WHERE子句来进行数据隔离。但此方法的缺点是编码工作量大、系统适应用户管理体系的弹性空间较小,一旦权限逻辑发生变动,就可能需要修改权限体系,导致所有的表或视图都必须修改。

为了解决此类问题,可以使用达梦数据库的虚拟专用数据库(VPD)技术,该技术提供了角色和视图无法提供的行级访问控制。
对于互联网访问,虚拟专用数据库可以确保在线银行的客户只能看到他们自己的帐户。Web托管公司可以在同一达梦数据库中维护多个公司的数据,但只允许每个公司查看其自身数据。
在企业内部,虚拟数据库可在应用程序部署方面降低拥有成本。可以在数据库服务器一次实现安全性,而不用在访问数据的每个应用程序中分别实现安全性。因为是在数据库中实施安全性,所以不管用户访问数据的方式如何,安全性较以前更高。

二、VPD工作原理
虚拟专用数据库是通过安全策略来实现行级访问控制的,具体来说,就是先将一个或多个安全策略与表或视图关联,对带安全策略的表进行直接或间接访问时,数据库将调用一个实施该策略的函数。策略函数返回一个访问条件(WHERE子句),即谓词。应用程序将它附加到用户的 SQL 语句,从而动态修改用户的数据访问权限。

也就是说,当你使用SQL语句访问带安全策略的表或视图时,VPD技术自动在该SQL语句上附加了SQL谓词(WHERE子句),例如,当你输入SELECT * FROM Person语句时,可以使用VPD添加WHERE DEPT = 10子句,这样查询出来的结果永远都是受到限制的。

三、达梦VPD示例
达梦数据库管理系统提供了 DBMS_RLS 包, DBMS_RLS 包通过策略(POLICY)管理方法来实现数据行的隔离。

下面我以一个实例来说明虚拟专用数据VPD的使用。

现在有一个订单表Orders,里面记录了销售部所有业务员的订单信息,要求每个销售员查询该表时,只能看到自己的订单,只有系统管理员能看到所有人的订单。

实现步骤如下:

--以系统管理员SYSDBA登录
CONN SYSDBA/SYSDBA
--创建DBMS_RLS包
SP_CREATE_SYSTEM_PACKAGES(1);

在这里插入图片描述

--创建测试用户(即业务员)
CREATE USER USER1 IDENTIFIED BY 123456789;
CREATE USER USER2 IDENTIFIED BY 123456789;
--授权
GRANT DBA TO USER1;
GRANT DBA TO USER2;
--创建测试表
DROP TABLE IF EXISTS SYSDBA.Orders;
CREATE TABLE SYSDBA.Orders(orderid int, salesman varchar(20), num int, amount int);

--插入测试数据
INSERT INTO SYSDBA.Orders VALUES(1,'USER1',10,100);
INSERT INTO SYSDBA.Orders VALUES(2,'USER1',20,200);
INSERT INTO SYSDBA.Orders VALUES(3,'USER2',30,300);
INSERT INTO SYSDBA.Orders VALUES(4,'USER2',40,400);
INSERT INTO SYSDBA.Orders VALUES(5,'USER2',50,500);
COMMIT;

此时尚未创建策略,分别使用系统管理员SYSDBA和普通用户USER1查询Orders表

--SYSDBA
CONN SYSDBA/SYSDBA
SELECT COUNT(*) FROM SYSDBA.Orders;

在这里插入图片描述

–USER1
CONN USER1/123456789
SELECT COUNT(*) FROM SYSDBA.Orders;
在这里插入图片描述
可以看到,此时,不同用户查询出的结果是一样的。
下面开始创建策略函数,然后创建策略组,并将策略应用到Orders表上

--创建策略函数,根据当前用户的不同,在SQL语句后面添加不同的WHERE子句
CREATE OR REPLACE FUNCTION FN_Orders_Condition(p_schema VARCHAR2,p_object VARCHAR2) 
RETURN VARCHAR2 IS
	v_user VARCHAR2(100) := CURRENT_USER();
	v_where_condition VARCHAR2(2000);
BEGIN
	IF v_user = 'SYSDBA' THEN
		v_where_condition := NULL;
	ELSE 
		v_where_condition := 'SALESMAN = ''' || v_user || '''';
	END IF;
	RETURN v_where_condition;
END;
--创建策略组
DBMS_RLS.CREATE_POLICY_GROUP(
	OBJECT_SCHEMA=>'SYSDBA',	--模式名
	OBJECT_NAME=>'ORDERS',	--表名
	POLICY_GROUP=>'PG_ORDERS'	--策略组名
);
--将策略应用到表Orders
DBMS_RLS.ADD_GROUPED_POLICY(
	OBJECT_SCHEMA=>'SYSDBA',	--表模式名
	OBJECT_NAME=>'ORDERS',	--表名
	POLICY_GROUP=>'PG_ORDERS',	--策略组名
	POLICY_NAME=>'ORDERS_POLICY',	--策略名(任意取,管理策略时使用)
	FUNCTION_SCHEMA=>'SYSDBA',	--策略函数的模式名
	POLICY_FUNCTION=>'FN_Orders_Condition',	--策略函数名
	STATEMENT_TYPES=>'select,update,delete,insert',	--应用策略的DML语句类型
	UPDATE_CHECK=>true,	
	ENABLE=>true	--是否启用策略
);

策略已启用,此时再用SYSDBA和USER1分别访问Orders表

--SYSDBA
CONN SYSDBA/SYSDBA
SELECT COUNT(*) FROM SYSDBA.Orders;

在这里插入图片描述

--USER1
CONN USER1/123456789
SELECT COUNT(*) FROM SYSDBA.Orders;

在这里插入图片描述
可以看到,此时SYSDBA和USER1查询的结果已经不一样了,SYSDBA仍然能查询所有的五行数据,而USER1只能查询自己的两行数据了。

下面利用USER1分别尝试一下SELECT, UPDATE,DELETE和INSERT的使用效果:

--USER1
CONN USER1/123456789
SELECT * FROM SYSDBA.Orders;
UPDATE SYSDBA.Orders SET SALESMAN = 'USER2' WHERE orderid = 1;
DELETE FROM SYSDBA.Orders WHERE SALESMAN = 'USER2'
INSERT INTO SYSDBA.Orders VALUES(6,'USER2',60,600);

执行结果如下:
在这里插入图片描述
可以看到,USER1只能查询到自己的两行数据,试图UPDATE\DELETE\INSERT别的用户数据均不能成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值