2011-09-17 49 views
0

我們有表的數據庫,使用Oracle 9i,(9.2),我們必須做出政策SELECT查詢,一些用戶組可以訪問確切行和一些不能,地規範它的觀點來解決:如何阻止在Oracle 9i中選擇的行?

  • 做一些查看錶
  • 起源

但是有一個問題,不斷變化的表名,我們不能改變表的名稱,它的官僚主義問題。

最後,它是一些機制或觸發器(沒有觸發器的選擇,但只是例子)來控制行訪問?

對不起,如果問題是假的,我沒有太多的DB經驗。

回答

4

一種選擇是爲相關表格創建一個Virtual Private Database policy

從演講中,我做了幾年前

設置環境

-- The SEMOP user has been granted the following privileges 
-- CREATE SESSION 
-- CREATE PROCEDURE 
-- CREATE ANY CONTEXT 
-- UNLIMITED TABLESPACE 
-- CREATE TABLE 
-- CREATE SEQUENCE 
-- EXECUTE ON DBMS_RLS 
-- EXECUTE ON DBMS_FGA 
-- SELECT ON DBA_FGA_AUDIT_TRAIL 

conn oow2009/oow2009; 

create table patient (
    patient_id   number primary key, 
    patient_first_name varchar2(30), 
    patient_last_name varchar2(30), 
    vip_flag   char(1) 
); 

create table service (
    service_id   number primary key, 
    service_name  varchar2(30) 
); 

create table doctor (
    doctor_id   number primary key, 
    doctor_first_name varchar2(30), 
    doctor_last_name varchar2(30), 
    service_id   number references service(service_id) 
); 

create table admission (
    admission_id  number primary key, 
    patient_id   number references patient(patient_id), 
    service_id   number references service(service_id), 
    primary_doctor_id number references doctor(doctor_id), 
    admission_date  date, 
    discharge_date  date 
); 

begin 
    insert into patient(patient_id, patient_first_name, patient_last_name, vip_flag) 
    values(1, 'Barack', 'Obama', 'Y'); 
    insert into patient(patient_id, patient_first_name, patient_last_name, vip_flag) 
    values(2, 'Larry', 'Ellison', 'Y'); 
    insert into patient(patient_id, patient_first_name, patient_last_name, vip_flag) 
    values(3, 'Justin', 'Cave', 'N'); 
    insert into patient(patient_id, patient_first_name, patient_last_name, vip_flag) 
    values(4, 'Jane', 'Doe', 'N'); 

    insert into service(service_id, service_name) 
    values(11, 'Obstetrics'); 
    insert into service(service_id, service_name) 
    values(12, 'Cardiac'); 
    insert into service(service_id, service_name) 
    values(13, 'Opthamology'); 
    insert into service(service_id, service_name) 
    values(14, 'Emergency'); 

    insert into doctor(doctor_id, doctor_first_name, doctor_last_name, service_id) 
    values(21, 'William', 'Mayo', 14); 
    insert into doctor(doctor_id, doctor_first_name, doctor_last_name, service_id) 
    values(22, 'George', 'Minot', 13); 
    insert into doctor(doctor_id, doctor_first_name, doctor_last_name, service_id) 
    values(23, 'Richard', 'Morton', 12); 
    insert into doctor(doctor_id, doctor_first_name, doctor_last_name, service_id) 
    values(24, 'Carl', 'Jung', 11); 
    insert into doctor(doctor_id, doctor_first_name, doctor_last_name, service_id) 
    values(25, 'Joseph', 'Lister', 12); 

    -- Obama has been admitted 3 times, twice for heart tests and once for an eye test 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(31, 1, 12, 23, date '2009-04-01', date '2009-04-01'); 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(32, 1, 12, 25, date '2009-05-03', date '2009-05-03'); 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(33, 1, 13, 22, date '2009-05-03', date '2009-05-03'); 

    -- Ellison was admitted to the emergency department following a yachting accident 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(34, 2, 14, 21, date '2009-07-01', date '2009-07-03'); 

    -- Justin was admitted earlier today for an eye exam and hasn't been discharged 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(35, 3, 13, 22, date '2009-09-24', null); 

    -- Jane was admitted to obstatrics 
    insert into admission(admission_id, patient_id, service_id, primary_doctor_id, admission_date, discharge_date) 
    values(36, 4, 11, 24, date '2009-08-01', date '2009-08-10'); 
end; 
/

創建安全上下文

create or replace context oow2009_ctx 
using pkg_secure_context;  

create or replace package pkg_secure_context 
as 
    procedure login(p_doctor_first_name IN doctor.doctor_first_name%TYPE, 
        p_doctor_last_name IN doctor.doctor_last_name%TYPE); 

    procedure logout;     
end; 
/

create or replace package body pkg_secure_context 
as 
    procedure login(p_doctor_first_name IN doctor.doctor_first_name%TYPE, 
        p_doctor_last_name IN doctor.doctor_last_name%TYPE) 
    as 
    l_doctor_id doctor.doctor_id%TYPE; 
    begin 
    SELECT doctor_id 
     INTO l_doctor_id 
     FROM doctor 
    WHERE doctor_first_name = p_doctor_first_name 
     AND doctor_last_name = p_doctor_last_name; 

    dbms_session.set_context('oow2009_CTX', 
           'DOCTOR_ID', 
           to_char(l_doctor_id)); 
    end login;    

    procedure logout 
    as 
    begin 
    dbms_session.clear_context('oow2009_CTX'); 
    end logout;  
end; 
/ 

創建策略函數

create or replace function policy_view_own_patients(schema_p IN VARCHAR2, 
                table_p IN VARCHAR2) 
    return VARCHAR2 
is 
begin 
    return 'patient_id IN 
      (SELECT patient_id  
       FROM admission 
       WHERE primary_doctor_id = 
         SYS_CONTEXT(''oow2009_CTX'', ''DOCTOR_ID''))'; 
end; 
/

創建行級安全策略

begin 
    dbms_rls.add_policy (
    object_schema => 'oow2009', 
    object_name => 'PATIENT', 
    policy_name => 'VIEW_OWN_PATIENTS', 
    policy_function => 'POLICY_VIEW_OWN_PATIENTS' 
); 
end; 
/

該查詢返回0行現在

select patient_first_name || ' ' || patient_last_name patient_name, 
     service_name, 
     doctor_last_name, 
     admission_date, 
     discharge_date 
    from patient p, 
     doctor d, 
     service s, 
     admission a 
where p.patient_id = a.patient_id 
    and a.service_id = s.service_id 
    and a.primary_doctor_id = d.doctor_id 
order by patient_last_name; 

如果你登錄爲威廉·梅奧,但是

exec pkg_secure_context.login('William', 'Mayo'); 

同樣的查詢返回行但只有那些爲Mayo的患者排隊的人。其他行繼續被過濾掉

select patient_first_name || ' ' || patient_last_name patient_name, 
     service_name, 
     doctor_last_name, 
     admission_date, 
     discharge_date 
    from patient p, 
     doctor d, 
     service s, 
     admission a 
where p.patient_id = a.patient_id 
    and a.service_id = s.service_id 
    and a.primary_doctor_id = d.doctor_id 
order by patient_last_name; 

你的政策功能,可以驅除當前登錄的用戶或其他任何一條信息,如果你不想要或需要的安全環境。

+2

+1順便說一句Oracle Row-Level-Security需要Enterprise Edition許可證。 – APC