如何在PL / SQL中动态调用包方法列表

Din*_*age 1 oracle plsql dynamic

我有一种情况,我想从具有不同参数的游标执行动态获取的方法。Get_Parameter_Value___(head_rec_.objkey,parameter_);如下面的示例所示,这些参数值在循环中被替换(使用)为值。

PROCEDURE Dynamic_exe(
    keyvalue_ IN VARCHAR2)
IS 
param_str_        VARCHAR2(2000);
temp_param_str_   VARCHAR2(2000);
method_stmt_      VARCHAR2(100);

CURSOR get_method IS
  SELECT exe_method
  FROM method_tab

BEGIN

param_str_        := Substr(rec_.exe_method,Instr(rec_.exe_method,'(')+1,(Instr(rec_.exe_method,')')-1)-Instr(rec_.exe_method,'('));
temp_param_str_   := param_str_;
method_stmt_      := rec_.exe_method;

WHILE temp_param_str_ IS NOT NULL LOOP
   IF (Instr(temp_param_str_,',') > 0 )THEN                
       parameter_          := trim(Substr(temp_param_str_,1,Instr(temp_param_str_,',')-1));
       temp_param_str_     := Substr(temp_param_str_,Instr(temp_param_str_,',')+1);
   ELSE
      parameter_          := trim(temp_param_str_);
      temp_param_str_     := NULL;
   END IF;
   parameter_value_  := Get_Parameter_Value___(head_rec_.objkey,parameter_);            
   method_stmt_      := REPLACE(method_stmt_,parameter_,''''||parameter_value_||'''');
END LOOP; 

FOR rec_ IN get_method LOOP
   EXECUTE IMMEDIATE 'BEGIN '||method_stmt_||'; END;';
END LOOP;

END Dynamic_exe;
Run Code Online (Sandbox Code Playgroud)

这是不安全的,可以为此执行SQL注入,我需要一个与绑定变量关联的解决方案,有人对此有解决方案吗?

Jon*_*ler 5

您可以通过使用DBMS_ASSERT.SQL_OBJECT_NAME保护方法名称以及使用DBMS_SQL和绑定变量保护参数来消除SQL注入的可能性。

DBMS_ASSERT.SQL_OBJECT_NAME如果该值与现有对象不同,则抛出错误。(尽管对于程序包,它仅检查程序包名称是否存在,而不检查过程名称。但是,过程名称必须仍然是实际名称。)

例如,如果包名称存在,该函数将简单地返回名称:

SQL> select dbms_assert.SQL_OBJECT_NAME('test_package.test_procedure') name from dual;

NAME
--------------------------------------------------------------------------------
test_package.test_procedure
Run Code Online (Sandbox Code Playgroud)

但是任何SQL注入恶作剧都会引发异常(您可以在必要时捕获并处理):

SQL> select dbms_assert.sql_object_name('; delete from employees;') from dual;
select dbms_assert.sql_object_name('; delete from employees;') from dual
       *
ERROR at line 1:
ORA-44002: invalid object name
ORA-06512: at "SYS.DBMS_ASSERT", line 401
Run Code Online (Sandbox Code Playgroud)

而不是将整个语句构建为字符串,而是添加:bind_variable_nDBMS_SQL运行它。

因此,最终的字符串将如下所示(在循环中添加绑定变量编号):

method_stmt_ := 'begin '||method_name||'(:1, :2); end;';
Run Code Online (Sandbox Code Playgroud)

执行动态数量的绑定变量require DBMS_SQL.BIND_VARIABLE。从本地动态SQL切换DBMS_SQL到恼人的过程,但这将使您传递绑定变量而无需担心注入。