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

Posted

技术标签:

【中文标题】如何在Oracle中添加一个策略,用户可以从表中选择所有数据,并且只能插入、更新、删除有条件的数据【英文标题】:How to add a policy in Oracle that a user can select all data from table and only can insert,update, delete his data with condition 【发布时间】:2020-06-06 11:27:00 【问题描述】:

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

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 政策:

ANNU 只能选择和修改她的数据。 THEOTA 无法选择和修改任何数据。 HANN 可以选择所有数据,但只能修改(插入、删除、更新)“假日”列中日期大于当前日期的日期(不能修改部分日期)

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

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 应用合适的策略。任何人都可以提供一些想法。

【问题讨论】:

【参考方案1】:

编辑:其他东西突然出现在我身上,再次查看 - DO NOT GRANT EXECUTE ON DBMS_RLS TO 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 的“Guarding Your Data Behind a Hard Shell PL/SQL API”中提供了有关该技术的完整文章。

【讨论】:

以上是关于如何在Oracle中添加一个策略,用户可以从表中选择所有数据,并且只能插入、更新、删除有条件的数据的主要内容,如果未能解决你的问题,请参考以下文章

IOS:当用户选择行时,从表视图连接外围设备

如何从表视图中添加/删除子视图

如何签入用户已在 Google recaptcha 中选中复选框的 js?

在Oracle中从表中删除重复行

如何检查是不是在 qtablewidget 中选中了复选框?

如何编写 SQL 查询以从表中提取 50% 的记录?