我正在开发一个oracle DB的web界面,其中: -
我创建了一个只读用户,可以访问该数据库中的任何表(NOT SYS)。
现在,我面临的问题是: - 1.如果该DB具有两个模式schema1和schema2,并且用户可以根据元数据访问schema1,并且如果他尝试运行schema2.table,则它将运行,因为read_only用户具有any_table特权。 2.他可以对all_tables(非空闲)运行查询
这可以通过以下方式解决: - 方法1:为每个模式创建用户并向该用户授予schema.table *特权。 问题: - 1.如果有100个模式,那么将有100个这样的用户。 2.如果架构中有新表,则需要为新表授予显式权限。
方法2:我正在考虑使用Regex方法来解析用户提供的查询,并且如果他被批准为schema1,则只允许schema1.table。如果他试图运行schema2.table,它将会失败。
问题: - 可能存在许多极端情况,例如子查询,连接等。
有没有更好的方法来解决这个问题。
答案 0 :(得分:1)
您似乎在描述一个普通的客户端 - 服务器方案。
如果您的最终用户是您正在描述的数据库模式,那么您应该实现数据库“角色”。分配对象访问数据库“角色”,然后根据您的安全定义将这些“角色”分配给最终用户。
http://docs.oracle.com/database/121/SQLRF/statements_6014.htm
要避免使用“schema1.table”和“schema2.table”,您可以实现数据库同义词。
https://docs.oracle.com/database/121/SQLRF/statements_7001.htm
使用“角色”+“同义词”,您将获得足够的控制(安全性)和轻松管理。
这里有一些Oracle安全准则:
http://docs.oracle.com/cd/B28359_01/network.111/b28531/guidelines.htm#DBSEG009
http://www.oracle.com/technetwork/articles/entarch/arch-approach-inf-sec-360705.pdf
答案 1 :(得分:1)
忘记解析,几乎不可能准确地解析Oracle SQL。相反,请使用填充的PLAN_TABLE
EXPLAIN PLAN
找到依赖项。
explain plan set statement_id = 'UNIQUE_ID' for $$SELECT_STATEMENT$$
生成每个语句的执行计划。PLAN_TABLE
以查找查询引用的模式。基于一些快速测试,这似乎适用于表,系统表,DUAL,同义词和视图。
至少在这些情况下它不起作用。
优化程序转换,可以完全从计划中删除表。例如,下面的查询引用了TABLE3,尽管它没有出现在 执行计划,因为它没有被使用。这些都是罕见的情况,可能不是一个真正的问题。
select *
from table1
where exists (select (select count(*) from table3) from table2);
DBA_DEPENDENCIES
。<强>实施例强>
创建示例模式。
create table table1(a number);
create table table2(a number primary key);
此查询仅使用本地表,因此仅返回一个用户。
explain plan set statement_id = '1' for
select *
from table1
join table2
on table1.a = table2.a;
select distinct object_owner
from plan_table
where statement_id = '1'
and object_owner is not null;
OBJECT_OWNER
------------
JHELLER
此查询引用系统表并返回SYS模式,并且验证失败。
explain plan set statement_id = '2' for
select (select count(*) from all_objects)
from table1
join table2
on table1.a = table2.a;
select distinct object_owner
from plan_table
where statement_id = '2'
and object_owner is not null;
OBJECT_OWNER
------------
JHELLER
SYS
此查询使用DUAL,但验证失败。检测DUAL有点棘手,因为它不是真正的表。
explain plan set statement_id = '3' for
select (select count(*) from dual)
from table1
join table2
on table1.a = table2.a;
select distinct object_owner
from plan_table
where statement_id = '3'
and object_owner is not null
union all
select distinct 'SYS'
from plan_table
where statement_id = '3'
and operation = 'FAST DUAL';
OBJECT_OWNER
------------
JHELLER
SYS
<强>声明强>
在大多数情况下,我不建议使用此解决方案。我同意贾斯汀对这一要求的担忧。如果它遵循标准的Oracle安全方法,那么管理数百个模式和对象可能会更简单。而且最好不要迟早反对无理的“安全”请求。不幸的是,在实践中,这些战斗通常会丢失。