【问题标题】:Why doesn't PL/SQL respect privileges granted by Roles?为什么 PL/SQL 不尊重角色授予的权限?
【发布时间】:2015-08-08 06:51:46
【问题描述】:

执行 PL/SQL 块时,授予角色的任何权限都将被忽略。相反,您必须授予特定用户特定的授权才能运行它。如果我想授予 DBA 访问包、函数或过程的权限,我不能授予 DBA 角色授权。我必须为 DBA 角色中的每个用户授予授权,如果用户不再是 DBA,我必须删除他们的授权,并且我必须将授权添加到任何新的 DBA。

我发现这很难维护。

我的问题是为什么 PL/SQL 会这样工作? Oracle 做了哪些设计考虑来决定角色和 PL/SQL 应该如何协同工作?我一直找不到不是“就是这样”的答案。

【问题讨论】:

  • Tom kyte has a likely explanation:它可能会导致难以维护的依赖链(角色影响到角色影响到角色...)。
  • 这就是为什么您可能要指定一个特殊的functional用户ID来编译函数、过程和包的原因之一。
  • 您所描述的似乎没有意义。或者至少你遗漏了一些重要的要求。如果您拥有定义者权限存储过程,则可以通过角色向用户授予对该过程的访问权限,并且该用户拥有调用它所需的所有权限。用户将无法创建自己的存储过程来调用此过程,但通常有很多用户需要调用过程而很少需要定义自己的过程。让人类用户拥有生产对象通常会使事情变得一团糟。

标签: oracle plsql


【解决方案1】:

我认为这是一些历史遗产。当更改 ROLE 的对象权限时,Oracle 将重新编译大量 PL/SQL 存储代码。 PS:你也可以创建一个叫做“SCHEMA”的东西。

参见CREATE SCHEMA 声明。

【讨论】:

    【解决方案2】:

    也许我在这里没有正确理解某些事情,因为我做了你说做不到的事情。事实上,Oracle 文档说可以做到。查看this document 中有关过程安全的部分。 (@ibre5041) 无需重新编译任何内容,因为这些过程在所有者的权限下运行。仅检查用户(或他的角色)的权限是否允许他们运行该过程。 我错过了什么?

    【讨论】:

    • AFAIK 这是因为对象级别 privs。到角色,连同公共同义词可能会影响对象的可见性。从理论上讲,这可能会导致长依赖链。 (例如:Procedure 使用 table1(通过公共同义词),User 拥有 RoleA,RoleA 拥有 RoleB,table1 从 RoleB 被撤销 - 是否意味着 Procedure 无效?)。 PS:这就是我的理解。
    • @ibre5041 - (重新编译)用户拥有什么权限并不重要。如果过程所有者的权限发生变化,则只需要重新编译该过程。如果所有者可以访问 table1,在您的示例中,通过 RoleA,如您所描述的,那么是的,必须重新编译该过程。但如果用户对 table1 的权限发生变化,则不必重新编译该过程。即使用户无权访问表 1,但他有权运行由用户 all_ice 拥有的过程,并且 all_ice 对 table1 具有权限,该过程应该可以正常运行。
    【解决方案3】:

    否则,如果您删除一个角色,那么 PL/SQL 包在某些情况下会变为无效(没有重新编译的选项)。

    DROP ROLE ... 是 DCL(数据控制语言)语句。看起来 Oracle 决定:“PL/SQL 包不应被 DCL 语句变为无效”

    【讨论】:

    • DROP ROLE 是数据定义语言,我认为。修改角色或用户的权限都是DCL,所以我认为部分答案是不正确的。
    【解决方案4】:

    这可能是懒惰和SET ROLE 命令的结合。

    我不同意由于复杂的依赖关系而不允许这样做。 Oracle 已经管理了复杂的依赖关系。在 12c 中,可以将角色授予对象。

    我认为对象不继承用户角色的真正原因是SET ROLE 命令。可以为用户分配一个角色,但可以在会话中打开和关闭它。这是一个愚蠢的功能,我从未见过它使用过。但理论上它需要在同一个会话或事务中重新编译,这真的很混乱。

    【讨论】:

    • @Offtopic。当您需要 2 因素身份验证时,SET ROLE 很方便。 (当角色受密码保护时)。用户知道它自己的密码,并且第二个角色密码在应用程序中是“硬编码的”。然后,即使用户能够通过 SQLPlus 连接到数据库,他也无法在那里做任何事情,因为他无法启用应用程序特定角色。 PS:好点。
    • @ibre5041 这是有道理的。但是,那将是two-step authentication, not two-factor authentication
    【解决方案5】:

    我认为您可能正在为调用者权利与定义者权利而争吵。

    来自Oracle docs

    在服务器调用期间,当 DR 单元被推入调用堆栈时, 数据库存储当前启用的角色和当前值 CURRENT_USER 和 CURRENT_SCHEMA。然后它同时改变了 CURRENT_USER 和 CURRENT_SCHEMA 到 DR 单元的所有者,并且只启用 角色 PUBLIC。 (存储的和新的角色和值不一定 不同。)当 DR 单元从调用堆栈中弹出时, 数据库恢复存储的角色和值。相反,当 IR 单元被压入或弹出调用堆栈,其值 CURRENT_USER 和 CURRENT_SCHEMA,以及当前启用的角色 不变

    因此,如果您希望 Oracle “尊重角色授予的权限”,那么也许您想使用调用者权限(AUTHID CURRENT_USER 子句)

    【讨论】:

      猜你喜欢
      • 2019-05-16
      • 2017-02-03
      • 2015-01-13
      • 2018-10-11
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多