【问题标题】:Oracle: Read-only access to the schema for another user?Oracle:另一个用户对架构的只读访问权限?
【发布时间】:2014-03-09 11:58:54
【问题描述】:

我有一个架构和一个同名用户:products。对于开发,我想在 Java 应用程序中以只读模式使用它。因此,我为只读应用程序创建了一个新用户。

CREATE USER PRODUCTS_READONLY IDENTIFIED BY PRODUCTS_READONLY;
GRANT CREATE SESSION to PRODUCTS_READONLY;
BEGIN
  FOR tab IN (SELECT table_name FROM   all_tables WHERE  owner = 'PRODUCTS') LOOP
     EXECUTE IMMEDIATE 'GRANT SELECT ON PRODUCTS.'||tab.table_name||' TO PRODUCTS_READONLY';
  END LOOP;
END;

运行应用程序时出现表不存在的错误。在互联网上搜索解决方案,我遇到了SYNONYM。所以我在模式中添加了同义词:

CREATE SYNONYM PRODUCTS_READONLY FOR PRODUCTS;

现在,我的java 应用程序中出现此错误:

ERROR org.hibernate.util.JDBCExceptionReporter - ORA-17074 invalid name pattern.: PRODUCTS_READONLY.PRODUCT_TYPE

我的方法有什么问题?

--更新--

似乎在 10g (Oracle: is it possible to create a synonym for a schema?) 中删除了为模式创建同义词。如果我为目标架构中的每个对象创建架构,每次将表添加到目标架构或对目标架构中的任何其他对象进行任何其他更改时,我都必须这样做?听起来很麻烦……

--更新 2--

似乎带有alter session 的触发器是一种可能的解决方案,但是只要用户只有SELECT 权限,它就会使表成为只读吗?

【问题讨论】:

  • 为什么不获取到数据库的只读连接? (Connection.setReadOnly(true);)
  • 我不想碰 Java 应用程序。我们有几个带有框架的层,我们不明确使用连接。我会避免这样做,我想知道是否可以在数据库级别实现。
  • @wumpz:根据 JavaDocs,setReadOnly() 只是驱动程序“启用数据库优化”的提示,快速测试显示这不会阻止运行 DML 语句。
  • @a_horse_with_no_name 你能用详细的触发器描述/代码创建一个答案吗?谢谢。

标签: java oracle oracle11g


【解决方案1】:

如果您可以控制应用程序的连接方式(例如,连接池的初始化语句),您需要做的就是运行:

ALTER SESSION SET CURRENT_SCHEMA = PRODUCTS;

从那时起(在会话的生命周期内),将在 PRODUCTS 架构中搜索任何不合格的对象名称。

所有授予PRODUCTS_READONLY 的授权都将生效。会话将在用于登录的原始用户的凭据(和安全限制)下运行。

如果您无法更改建立或初始化连接的方式,则登录触发器也应完成此操作:

create or replace trigger logon_trg
  after logon on database
begin
    if (user = 'PRODUCTS_READONLY') then
      execute immediate 'alter session set current_schema = products';
    end if;
exception
  when others then null; -- prevent a login failure due to an exception
end logon_trg;
/

请注意,捕获任何异常至关重要,因为否则执行的 SQL 中的潜在错误将有效地将所有人从数据库中注销。因此,在将其投入生产之前,请谨慎使用并对其进行充分测试。

【讨论】:

    【解决方案2】:

    我不确定您是否可以为架构创建同义词。

    但是您可以为远程模式中的每个对象创建同义词,例如

    begin
      for c in (select t.table_name from table_privileges t where grantee = 'PRODUCTS_READONLY') loop
        execute immediate 'create synonym '||c.table_name||' for PRODUCTS.'||c.table_name;
      end loop;
    end;
    

    不要与 table_name 混淆,它在那里处理所有类型的对象。

    【讨论】:

    • 当我以 products_readonly 登录并执行语句时,我收到错误“表或视图不存在”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多