Php 分解字符串并调用动态函数

Php 分解字符串并调用动态函数,php,function,dynamic,explode,Php,Function,Dynamic,Explode,我有一个如下格式的字符串: function1!!param1||ignore!!param2&&function2!!param1||ignore!!param2||ignore!!param3 它拥有的函数数量是无限的(它们用&&&分割) 从上面的字符串生成的基本函数调用是: function1($param1,$param2); 第二个: function2($param1,$param2,$param3); 参数的数量是无限的。(它们不被调用函数和参数,这只是一个示

我有一个如下格式的字符串:

function1!!param1||ignore!!param2&&function2!!param1||ignore!!param2||ignore!!param3
它拥有的函数数量是无限的(它们用&&&分割)

从上面的字符串生成的基本函数调用是:

function1($param1,$param2);
第二个:

function2($param1,$param2,$param3);
参数的数量是无限的。(它们不被调用函数和参数,这只是一个示例)

很高兴回答任何问题!!我已经试过了&&然后!!但我不太明白如何使用动态参数调用动态函数

5.2的解决方案:

function function1( $a1, $a2 ) {
    echo $a1 . $a2;
}

function function2( $a1, $a2, $a3 ) {
    echo " ".$a1 . $a2 . $a3;
}
function explodemap($val) {
        $explode = explode( "!!", $val );
        return $explode[1];
}
$functions = explode( "&&", 'function1!!param1||ignore!!param2&&function2!!param1||ignore!!param2||ignore!!param3' );

foreach( $functions as $function ) {
    $split = explode( "||", $function );
    $weird_excalmation_split = explode("!!", $split[0] );
    $params = array_slice( $split, 1 );

    $params = array_map( "explodemap", $params );

    $fn_name = $weird_excalmation_split[0];
    array_unshift( $params, $weird_excalmation_split[1]  );

    call_user_func_array( $fn_name, $params );
}
使用:


在上面的评论中,我解释了为什么使用
eval()
是一个潜在的安全问题:

如果您从Android应用程序收到此数据,则表示您的 数据不安全,很容易被潜在的黑客更改。 如果您使用
eval()
执行收到的字符串,我可以每隔一天调用 通过更改函数名来创建PHP函数。例如,如果我改变
function1
在字符串中添加到
exec(“rm-rf/”);功能1
每个文件 将删除服务器上的,包括操作系统 (前提是您在服务器上启用了
exec()
,并且您的服务器 运行unix)。但是你可以看到
eval()
有多危险,所以千万不要使用 它


但是
调用用户函数数组()
安全吗

它更安全,但仍然不够安全。使用
eval()
我可以指定 函数名和参数一气呵成,因为 执行一个字符串。虽然这是不可能的
调用\u user\u func\u array()
,它仍然执行任何指定的函数, 这意味着我仍然可以做同样的事情。如果我能把你的字符串改成
exec!!rm-rf/
您仍然会遇到问题。真的,唯一好的 方法是对照白名单检查每个函数名 名字


你怎样才能保证这次行动的安全?您可以使用
开关
语句或\u array()中的
检查允许的函数。使用后者的示例如下:

<?php

// Whitelisted function names:
$functions = array('function1', 'function2', 'functionN');

// Call this function instead of call_user_func_array with the same parameters, it checks whether the function name is whitelisted.
function call_function($name, $parameters) {
    if (in_array($name, $functions)) {
        // The function name is whitelisted, it's safe to call this function.
        if (!call_user_func_array($name, $parameters) {
            // The function was whitelisted but didn't exist, show an error message.
        }
    } else {
        // A function was called that was not whitelisted! Write to log.
    }
}

?>


我没有测试它,但这应该是有效的。希望这有帮助

你可能不需要我告诉你这是一个非常糟糕的模式,但也许你继承了它。你不会说什么
ignore
做了什么…谢谢你的回答。我正在通过http post从一个android应用程序发送一个字符串,该应用程序存储用户离线时所做的所有事情。如果你知道一个更好的方法,我真的很高兴听到。我对我存储数据的方式也不是很满意。。。。(你是否否决了我的意见?)看一看,显然你必须不止一次地应用它,然后才能看到如何调用存储在字符串中的函数名。忽略是字符串中我在函数调用中不需要的其他内容。看看我的第一条评论。当用户在线时,我使用相同的模式,只是每个| |都是一个http post参数:?function1=param1&someignore=param2tank you@Havelock和所有其他给我提示的参数。将使用你们提供给我的信息,然后重试。按指定方式工作。。。有什么问题吗?谢谢!!看起来不错。如果你的答案有效,我会接受你的答案并试着理解它。它需要PHP5.4,如果你有较低的版本,它就必须重写一点。@Lorof PHP5.4是
explode(!!“,$val)[1]
(在早期的PHP中不能直接数组访问)所必需的,PHP5.3是传递给
array\u map
的匿名函数所必需的。你可以重写5.2版。主要的一点是
call\u user\u func\u array
,它是从PHP4或其他版本开始工作的。添加了5.2的解决方案。非常感谢你。
<?php

// Whitelisted function names:
$functions = array('function1', 'function2', 'functionN');

// Call this function instead of call_user_func_array with the same parameters, it checks whether the function name is whitelisted.
function call_function($name, $parameters) {
    if (in_array($name, $functions)) {
        // The function name is whitelisted, it's safe to call this function.
        if (!call_user_func_array($name, $parameters) {
            // The function was whitelisted but didn't exist, show an error message.
        }
    } else {
        // A function was called that was not whitelisted! Write to log.
    }
}

?>