Как заблокировать выделение строки в Oracle 9i? - PullRequest
0 голосов
/ 17 сентября 2011

У нас есть таблица в базе данных, с использованием Oracle 9i (9.2), мы должны создать политику для запроса SELECT, некоторые группы пользователей могут получить доступ к точной строке, а некоторые нет, стандартно это решается с помощью VIEW:

  • создание некоторой таблицы VIEW
  • изменение имени таблицы происхождения

Но есть проблема, мы не можем изменить имя таблицы, это проблемы бюрократии.

И, наконец, это какой-то механизм или триггеры (для SELECT нет триггеров, а только пример) для контроля доступа к строкам?

Извините, если вопрос глупый, у меня нет большого опыта работы с БД.

1 Ответ

4 голосов
/ 17 сентября 2011

Один из вариантов - создать Политику виртуальной частной базы данных для рассматриваемой таблицы.

Из презентации, которую я сделал пару лет назад

Настройкасреда

-- 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' );

тот же запрос теперь возвращает строки, но только те, которые строки для пациентов Мейо.Другие строки по-прежнему отфильтровываются

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;

Ваша функция политики может отключить пользователя, вошедшего в систему, или любую другую информацию, если вы не хотите или вам нужен безопасный контекст.

...