首页 > 解决方案 > 如何在Oracle中添加一个策略,用户可以从表中选择所有数据,并且只能插入、更新、删除有条件的数据

问题描述

我有一个像这样的对象名称。

grant execute on dbms_rls to public;
create table empholiday
(
    EmpNo number(5),
    Name nvarchar2(60),
    Holiday date
);
INSERT INTO empholiday VALUES (1,'HANN','02-JAN-2019');
INSERT INTO empholiday VALUES (2,'ANNU','12-MAY-2019');
INSERT INTO empholiday VALUES (3,'THEOTA','26-AUG-2019');

我创建了 3 个用户:HANN、ANNU、THEOTA 我想为这些用户制定 VPD 策略:

这是我到目前为止所做的:

create user HANN identified by 123456;
create user ANNU identified by 123456;
create user THEOTA identified by 123456;
create role emp;
grant connect to emp;
grant create session to emp;
grant emp to HANN;
grant emp to ANNU;
grant emp to THEOTA;
grant select,update,delete,insert on empholiday to ANNU;
drop function Annu_Theota;
--create function
create or replace function Annu_Theota (p_schema varchar2, p_obj varchar2)
return varchar2 as
l_user varchar2(20);
begin
  l_user := SYS_CONTEXT('userenv', 'SESSION_USER'); 
  if (l_user = 'ANNU') then
    return 'Name=' || '''' || l_user || '''';
  elsif (l_user = 'THEOTA') then
    return '1=0';
  end if;
end Annu_Theota;

begin
  dbms_rls.add_policy
    (object_schema=>'trongdat' 
    ,object_name=>'empholiday'  
    ,policy_name=>'HolidayControl' 
    ,policy_function=>'Annu_Theota_Hann' 
    ,statement_Types=>'SELECT,UPDATE,INSERT,DELETE'  
    );
end;

我不知道如何为此用户 HANN 应用合适的策略。任何人都可以提出一些想法。

标签: oraclesecuritypolicyvpd

解决方案


编辑:其他东西突然出现在我身上,再次查看这个 -不要将 DBMS_RLS 上的执行权限授予 PUBLIC !!!此功能仅在用户创建和更新策略时需要。通过将其授予公共,您已允许所有用户查看和禁用或删除任何策略并公开任何数据


使用 VPD 策略只会限制用户可见的行,有时甚至是列。您不能使用它们将业务逻辑应用于允许的列内容或限制用户仅更新特定列。您正在谈论的权限 - 插入、更新和删除 - 将始终适用于表中的所有列。鉴于您的要求的粒度级别 - 对值有特定限制的列级别,即 - 您应该考虑不允许直接更新表,而是使用 PL/SQL 函数作为 API 层来执行更新。

例如,使用以下过程创建一个名为 empholiday_pkg 的 PL/SQL 包:

  • get_data:从表中选择行的流水线函数
  • ins_data:在表中插入行的过程
  • upt_data:将更新应用于表的过程
  • del_data:从表中删除行的过程

与其直接将表上的“选择、插入、更新、删除”授予用户,不如授予他们对包的执行权限。然后在包的 PL/SQL 中包含您需要的任何业务逻辑 - 例如,根据角色或其他用户特征限制他们可以修改的列。

然后,用户将调用该包以获取数据或进行更改:

select * from empholiday_pkg.get_data();

execute empholiday_pkg.ins_data([put your parameters here]);

begin
    empholiday_pkg.upt_data([put your parameters here]);
    commit;
end;

如果您想单独控制对程序的访问,请为每个程序创建单独的单例包。使用包而不是独立过程允许您将 PL/SQL 代码包装在包主体中以确保安全。授予对包的执行权限仅允许用户在数据字典中查看包头,其中将完全公开独立过程。

另一个建议:不要将“提交”命令放在包过程本身中 - 就像您以前使用独立的插入/更新/删除命令一样处理它,以便每个用户都可以管理他们的事务,或者这样您可以在基本表格 DML 包之上构建更大的 API。

Bryn Llewellyn 的“在硬壳 PL/SQL API 后面保护您的数据”中提供了有关该技术的完整文章。


推荐阅读