首页 > 解决方案 > 防止 Oracle 包在生产中执行

问题描述

我创建了一个 Oracle PL/SQL 包,我想阻止它在生产环境或特定数据库中执行,这可能很危险。事实上,事实证明我拥有管理员权限,并且可能会无意中在生产环境中编译开发包。

我尝试使用类似于以下内容检查我的包正文中的上下文:

create or replace package body my_test_package is

    context varchar2(64);

    function get_context return varchar2 is
    begin
        -- return context: DEV or PROD
        ...
    end;

    -- list of other functions & procedures ....

    begin   
        if context = 'PROD' then
            dbms_standard.raise_application_error(-20001, 'production context, prevent execution of this package');
        end if;
end;

但是,我知道这是不好的解决方案,因为初始化时间只发生一次,如Oracle 文档所述:

包的初始化部分只起次要作用,因为与子程序不同,包不能被调用或传递参数。因此,包的初始化部分只运行一次,即在您第一次引用该包时。

因此,这意味着将执行第一个之后的所有后续过程调用,即使在生产环境中也是如此。例如:

-- production environment
begin
    my_test_package.dangerous_procedure();
exception when others then
    dbms_output.put_line('bypass context exception');
end;
my_test_package.dangerous_procedure(); ---> EXECUTED IN PROD :(

是否有常见的习惯用法或已知的方法来防止包在特定环境中执行?(例如,不必在包的每个过程/函数中复制相同的代码,以检查它是否有权执行)。

谢谢

标签: oracleplsqlpermissionspackage

解决方案


通常有相反的要求:即,您有在 PROD 中运行的进程,而您不想在 DEV 中运行(或不以相同的方式运行)。例如,您可能有一个程序生成一个文件并将其通过 FTP 发送给贸易伙伴。从 PROD 克隆后,您不希望它意外地在 DEV 中运行。

我们将需求的实现构建到我们的代码中,而不是依赖于数据库级别的东西,比如在某些环境中删除对象(或在克隆后不断地在 DEV 实例中重新安装东西)和/或撤销安全性。通过将东西构建到我们的代码中,我们不仅可以灵活地防止某些东西在一个或另一个实例中运行,还可以让它运行但以不同的方式运行(例如,生成 FTP 文件,但将其发送到测试服务器而不是贸易伙伴)。

为此,我们有一条具有生产数据库名称的数据(我们为此使用称为“配置文件值”的应用程序功能,但您可以将其放在自定义表中)。

然后,在任何环境敏感的过程中:

BEGIN
  l_db_name := xxcust_common_utils_pkg.get_production_dbname;  -- you write this function based on where you put the production database name...
  IF sys_context('USERENV','DB_NAME') = l_db_name THEN
    ... act like you want to in production
  ELSE
    ... act like you want to in non-production
  END IF;
END;

这很简单,但不幸的是确实需要编码。


推荐阅读