Vin*_*eJS 6 database oracle schema rights synonym
这是场景(简化示例):
我有一个名为ABC的Oracle用户/架构.ABC拥有一张叫做TRN的桌子.客户端代码以ABC形式连接到数据库,并从ABC.TRN中选择.
到现在为止还挺好.但是,我不希望客户端代码指定Oracle模式名称.现在我想我已经删除了引用模式的客户端代码中的所有引用,但我想测试它以确保.
所以我想创建一个名为DEF的新用户/模式,客户端将使用它来连接数据库.当客户端应用程序从ABC.TRN中选择时,它必须给出错误.但是,如果客户端应用程序从TRN(无模式名称)中选择,则它必须返回数据.
有办法做到这一点吗?请注意,DEF必须与ABC在同一个数据库中,只有一个表TRN表(由ABC拥有),我不能使用数据库链接.
我尝试创建一个新的XYZ用户,其同义词指向ABC.TRN并赋予它对ABC.TRN的选择权限.然后我创建了DEF用户,其同义词指向XYZ.TRN,并且给予DEF对XYZ.TRN的选择权限.这很有效但是Oracle很聪明地知道如果DEF有权从XYZ.TRN中选择,那么它也有权从ABC.TRN中进行选择,从而违背了本练习的目的,因为我希望这个案例给出错误.
给你...
没有简单的方法可以做到这一点.
一种方法是政治性的:机构代码审查,也许是对代码库的自动搜索,并且当人们这样做时只是拍手腕.
架构方法类似于您的三种架构结构,但有一个微妙的转折:中间的架构使用视图.因此,模式ABC拥有表并授予它们对模式XYZ的权限.Schema XYZ针对这些表构建简单视图(SELECT*,没有WHERE子句),并将视图权限授予模式DEF.Schema DEF只能从XYZ对象中选择.
当然,所有这些努力仍然不会阻止开发人员编码SELECT * FROM xyz.whatever.在这种情况下,我推荐你的第一个建议8-)
实际上有一种,真的很邪恶的方式来做到这一点.在面向架构的应用程序(DEF)中使用同义词,然后更改数据拥有架构(ABC)的名称.
当然,如果您的安装脚本完全是参数化的,并且没有自己的硬编码模式名称,那么您应该只尝试此策略.
你真的需要抛出错误吗?或者您只是需要验证应用程序是否使用完全限定名称(即ABC.TRN)?
假设您只是想验证应用程序没有使用完全限定名称,并且抛出错误只是您想要通知您的机制,您可以通过V$SQL在应用程序运行时查询来验证代码.  V$SQL列出Oracle中共享池中的所有SQL语句.如果在应用程序运行时定期查询该表,您将看到它发出的所有SQL语句.然后,您可以记录使用完全限定名称的任何语句.
例如
CREATE OR PROCEDURE look_for_abc_trn
AS
BEGIN
  FOR x IN (SELECT *
              FROM v$sql
             WHERE upper(sql_fulltext) LIKE '%ABC.TRN%')
  LOOP
    INSERT INTO log_of_bad_sql( sql_fulltext, <<other columns>> )
      VALUES( x.sql_fulltext, <<other columns>> );
  END LOOP;
END;
如果在应用程序运行时每隔几分钟运行该过程,您将看到任何使用完全限定名称的SQL并在LOG_OF_BAD_SQL表中记录该语句.对于编写良好的系统来说,每隔几分钟就可能有点过分了,您只需要确保它的运行频率高于语句在共享池中的老化程度.如果您的应用程序没有正确使用绑定变量,则可能需要每隔几分钟才能避免遗漏任何内容.
改变会话怎么样?
         ALTER SESSION SET CURRENT_SCHEMA = schema
这将允许您以用户身份登录,该用户已被授予对模式 X 拥有的表的选择权限,并执行将会话更改为模式 X 的 SP。前端代码不会知道发生了这种情况。
但是,如果您的前端代码指定架构 X:
           select * from X.tableName
我认为这不会引发错误。
也许您可以解释为什么客户端代码在使用正确的当前架构名称时收到错误很重要?
是否可以创建一个新模式,转移旧模式对象的所有权,然后删除旧模式,然后使用上面的方法?
PS 请参阅登录后触发器:http://psoug.org/reference/system_trigger.html
PPS 既然您已经详细说明了您的要求:
...该表可能是使用数据库链接的同义词,或者该表可能由多个模式托管,每个模式针对不同的版本。应由数据库来解析客户端应用程序引用的对象的实际位置。
例如,如果对象的位置不在 CURRENT_SCHEMA 中,而是在其他某个架构中,这两个架构恰好都有名为 CUSTOMER 的表,则数据库引擎将不知道客户端应用程序发送给它的语句应该引用如果表名不那么限定,则使用其他模式。这意味着引擎不具备一定程度的元知识,尽管它为开发人员提供了以存储过程和触发器的形式创建此类智能的工具,并授予/撤销对对象的控制。
成功地将这种智能放入后端的最佳机会是撤销对表和视图的所有直接权限,并要求客户端应用程序通过存储过程访问对象,因为数据库引擎本身不知道应用程序发布之类的事情水平。我认为没有纯粹的声明性方法可以实现它。这在很大程度上必须是程序性的。您自己的后端逻辑必须承担在不同模式中的同名对象之间进行仲裁的责任。也就是说,像 AFTER LOGON 触发器和 ALTER SCHEMA 这样的功能应该对您有帮助。
| 归档时间: | 
 | 
| 查看次数: | 4695 次 | 
| 最近记录: |