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



我有一个场景,我想从具有不同参数的游标中执行动态获取的方法。这些参数值将替换为循环中的值(使用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;

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

通过使用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

但是任何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

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

所以最终的字符串将看起来像这样(在循环中添加绑定变量号):

method_stmt_ := 'begin '||method_name||'(:1, :2); end;';

执行动态数量的绑定变量需要DBMS_SQL.BIND_VARIABLE。 从本机动态 SQL 切换到DBMS_SQL会很烦人,但它可以让您传入绑定变量而没有任何注入问题。

最新更新