尝试限制对Oracle DB的访问以运行查询 - 设计建议

时间:2015-07-16 19:06:27

标签: regex database oracle database-administration

我正在开发一个oracle DB的web界面,其中: -

  1. 用户可以要求访问特定模式
  2. 如果他被授予访问权限,他应该能够仅在该模式上运行查询。 (所有其他查询,如其他模式,sys表,all_tables,dual应该被拒绝)
  3. 我创建了一个只读用户,可以访问该数据库中的任何表(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,它将会失败。

    问题: - 可能存在许多极端情况,例如子查询,连接等。

    有没有更好的方法来解决这个问题。

2 个答案:

答案 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找到依赖项。

  1. 为每个语句生成唯一ID。
  2. 通过运行explain plan set statement_id = 'UNIQUE_ID' for $$SELECT_STATEMENT$$生成每个语句的执行计划。
  3. 查询PLAN_TABLE以查找查询引用的模式。
  4. 基于一些快速测试,这似乎适用于表,系统表,DUAL,同义词和视图。

    至少在这些情况下它不起作用。

    1. 优化程序转换,可以完全从计划中删除表。例如,下面的查询引用了TABLE3,尽管它没有出现在 执行计划,因为它没有被使用。这些都是罕见的情况,可能不是一个真正的问题。

      select *
      from table1
      where exists (select (select count(*) from table3) from table2);
      
    2. 程序代码(如函数和类型)不会显示在执行计划中。保护自定义过程代码可能需要不同的方法。例如,可能需要使用游标中的SELECT语句动态创建临时过程,然后以递归方式检查DBA_DEPENDENCIES
    3. <强>实施例

      创建示例模式。

      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安全方法,那么管理数百个模式和对象可能会更简单。而且最好不要迟早反对无理的“安全”请求。不幸的是,在实践中,这些战斗通常会丢失。