在開始對ORACLE的Virtual Private Database的介紹之前
筆者想就ROW
RULE control(行記錄級訪問控制)的概念簡單地說幾句
行記錄級訪問控制問題的提出和意義? 企業的應用系統都離不開數據庫系統
數據庫系統的權限控制是很重要的一個環節
大型數據庫系統(ORACLE
DB
SYBASE
MS SQLSERVER)都提供完善的用戶管理機制
從而可以嚴密地控制數據庫對象(表
視圖
函數
存儲過程
程序包等等)的訪問
但是
這往往是對象級別的
隨著商務需求地不斷地提出
出現了對於行記錄控制的要求:
) 數據查詢和報表輸出數據需要能夠進行有效地隔離
如在一個簡單地銷售數據統計應用中
大區經理
地區經理和銷售員查詢的數據就不同
) ASP(應用服務供應商)系統出現
在系統結構上
就出現了許多企業用戶的數據都會存放在同一個數據庫種
但是系統需要能夠有效地隔離
為了滿足這樣的需求
在業務數據表需要中加上一些字段來進行控制
應用的開發往往會另行開發很多代碼來實現行記錄控制
但是
隨著業務的變化
我們會發現開發和維護這種管理需求的成本越來越高
我們需要尋找一種新的解決方案
能夠使應用系統的架構設計簡單
擴展性強
管理和維護的成本很低
ORACLE
i的一個新特性Virtual Private Database
ORACLE
i提供了一個新的特性
來實現行級規則的控制
稱之為Virtual Private Database
充分利用
i提供的Virtual Private Database技術
可以實現
一個數據庫Schema的數據同時給多個數據庫用戶訪問
但是又能很好地隔離各自的數據內容
顯然
這已經不是原來的對象級的控制的概念
下面是筆者的體驗
寫下來
供大家參考
我先通過一個簡單的例子
來說明ORACLE
i的這個新特性(需ORACLE
i的企業版才支持)
環境:Windows
Server + ORACLE
(Enterprise Edition)
在SCOTT用戶下
有一個Customers表
記錄著客戶資料
以後為每個客戶分配一個ORACLE數據庫登陸賬號
客戶可以登陸
查詢自己的訂單情況
那麼
我們需要做的就是能夠把每個登陸賬號和客戶代碼對應起來
就是說要實現一個映射關系
當然
通過自己建關系映射表
寫代碼做
也可以實現
但是ORACLE
I把這一切變地非常簡單(我接下來的介紹都會圍繞著ORACLE
i這項技術是我們的工作如何更加簡單
如何更加容易控制
請記住
這是筆者寫這篇文章的目的)
建立一個SECUSR的賬號
用於權限控制用
connect system/manager@oracle;
create user secusr identified by secusr;
grant connect
resource
dba to secusr;
把Customers的查詢權利賦予secusr
connect scott/tiger@oracle;
grant select on
Customers
to secusr;
連接到secusr用戶
connect secusr/secusr@oracle;
創建上下文
create context Customer_context USING secusr
CUSTOMER_SECURITY_CONTEXT;
創建程序包customer_security_context
create or replace package
secusr
customer_security_context is
procedure set_customerid;
end;
create or replace package body
secusr
Customer_security_context is
procedure set_customerid is
begin
IF SYS_CONTEXT(
USERENV
SESSION_USER
)=
SCOTT
THEN
DBMS_SESSION
SET_CONTEXT(
customer_context
customerid
ALFKI
);
END IF;
end;
end;
授權
grant execute on secusr
Customer_security_context to public;
ORACLE
i中提供了Context(連接上下文)的概念
類似於asp中的session
你可以為當前這個連接設置多個全局變量
記錄信息
這個信息一直保持到連接被釋放
上面的代碼
就是為用SCOTT賬號登陸的連接
進行了一次客戶代碼的映射(SCOTT
>ALFKI)
而且
隨時可以SYS_CONTEXT來查詢
具體代碼如下
SQL> connect scott/tiger@oracle;
已連接
SQL> execute secusr
Customer_security_context
set_customerid;
PL/SQL 過程已成功完成
SQL> select SYS_CONTEXT(
CUSTOMER_CONTEXT
CUSTOMERID
) FROM DUAL;
SYS_CONTEXT(
CUSTOMER_CONTEXT
CUSTOMERID
)
ALFKI
但是
我覺的還不夠
能夠做到每個連接建立的時候
就自動完成這種映射
令人高興的是
ORACLE
i提供了系統級的觸發器
讓我輕松地實現
SCOTT用戶登陸觸發器
connect system/manager@oracle
CREATE OR REPLACE TRIGGER scott
tg_set_usr_context
AFTER LOGON ON DATABASE
BEGIN
secusr
customer_security_context
set_customerid;
END;
斷掉connection
重新登陸
Oracle
i Enterprise Edition Release
Production
With the Partitioning option
JServer Release
Production
SQL> CONNECT scott/tiger@oracle
已連接
SQL> select SYS_CONTEXT(
CUSTOMER_CONTEXT
CUSTOMERID
) FROM DUAL;
SYS_CONTEXT(
CUSTOMER_CONTEXT
CUSTOMERID
)
ALFKI
SQL>
好了
夠簡單吧
采用Virtual Private Database如何達到SQL DML上的數據控制訪問要求呢?
Virtual Private Database技術可以對一張表的記錄設置DML操作的過濾策略
ORACLE
i提供了POLICY的概念
並且為此配備了一套系統程序包
來完成設置
下面
我來介紹一下
connect secusr/secusr@oracle
做一個函數
返回對應的過濾條件
create or replace package secusr
customer_security is
function customer_sec
return VARCHAR
;
end;
create or replace package body secusr
customer_security
is
function customer_sec(d
varchar
d
varchar
)
return varchar
IS
begin
IF SYS_CONTEXT(
USERENV
SESSION_USER
) IN (
SYS
SYSTEM
SECUSR
) THEN
RETURN NULL;
ELSE
RETURN
customerid=
|| SYS_CONTEXT(
CUSTOMER_CONTEXT
CUSTOMERID
) ||
;
END IF;
end;
end;
設置表數據的分割過濾
EXECUTE DBMS_RLS
ADD_POLICY(
SCOTT
Customers
Customers_sec_Policy
SECUSR
customer_security
customer_sec
SELECT
UPDATE
DELETE
);
customer_security程序包的customer_sec函數實現了
根據但前的CONTEXT中CUSTOMERID的內容
來返回一個過濾的策略
函數的參數形式是固定的
通過dbms_rls程序包的ADD_POLICY過程
把策略條件同表綁定以來
以後
每次select
update
delete都會自動應用這個策略
好了
現在我們來測試一下
用SCOTT登陸
只能看到自己的信息
SQL> connect scott/tiger@oracle;
已連接
SQL> select customerid
city from
Customers
;
CUSTOMERID CITY
ALFKI Berlin
用SYSTEM登陸
可以看到所有的
SQL> connect system/manager@oracle;
已連接
SQL> select customerid
city from
SCOTT
Customers
;
CUSTOMERID CITY
ALFKI Berlin
ANATR México D
F
ANTON México D
F
AROUT London
BERGS Lule? D
F
BLAUS Mannheim
BLONP Strasbourg
BOLID Madrid
BONAP Marseille
BOTTM Tsawassen
BSBEV London
非常好
完全滿足了要求
現在可以放心地把SCOTT賬號給客戶(ALFKI)了
客戶可以查詢自己的訂單情況
當然只能是自己的
SQL> SELECT a
orderid
a
customerid
a
orderdate
sum(c
UnitPrice*c
Quantity*(
c
Discount)) as TotalMoney
FROM
Orders
a
Customers
b
Order Details
c
From:http://tw.wingwit.com/Article/program/Oracle/201311/18040.html