5 php evaluation eval expression-evaluation
我需要使用 PHP 在服务器上处理一些用户提供的代码。该代码将涵盖一些非常基本的编程功能,例如:变量、文字、(最好)函数和一些相关操作。
一种选择是使用 的危险函数eval()。对于我的具体情况,除了安全问题和性能瓶颈之外,它的功能极其丰富且冗余。使用消毒令牌可以token_get_all()防止墨菲,而不是马基雅维利!不管它有什么缺点,它确实能够实现我一直渴望实现的目标。
我还检查了 Symphony 的ExpressionLanguage;它有一些缺点:
唉! 更复杂的ExpressionLanguage就足够了。
我正在寻找一种能够为用户提供一些非常基本的“编程”能力的东西。有这样的事吗,如果有的话,那是什么?(即使它是用另一种语言编写的,但可以在服务器上以某种方式使用。)如果这样的东西不存在,那么我应该如何对待eval()不吸引我?!或者,作为最后的手段,我如何设计这样一个简单的编程功能?(请详细说明事项:)
if和一个重复结构(例如:for循环)也许你可以看一下 Docker。例如,您可以将用户代码复制到服务器上的文件中(而不执行它),然后在容器内运行它。这将使您能够:
一些例子:
docker run -v "$PWD":/usr/src -w /usr/src --rm php:7.4.5 php ./myScript.php
Run Code Online (Sandbox Code Playgroud)
这将在基于 php 7.4.5 的新容器中执行文件 myScript.php,完成后容器将被删除。
使用另一个 PHP 版本同样的事情:
docker run -v "$PWD":/usr/src -w /usr/src --rm php:5.6 php ./myScript.php
Run Code Online (Sandbox Code Playgroud)
有用的链接:
关于表演的编辑:
显然,使用容器运行代码比直接从 PHP 运行代码要长。
例如,我们可以运行以下代码来测试它:
<?php
function reverseArray(array $array): array {
for ($i = 0; $i < count($array) / 2; $i++) {
$tmp = $array[$i];
$array[$i] = $array[count($array) -1 - $i];
$array[count($array) - 1 - $i] = $tmp;
}
return $array;
}
$tabToReverse = [5, 8, 95, 10, 6, 17, 42, 20];
echo 'Reversed array : '."\n";
echo implode(' ', reverseArray($tabToReverse));
Run Code Online (Sandbox Code Playgroud)
相同的代码,但有语法错误:
<?php
// syntax error
function reverseArray($array: array): array {
for ($i = 0; $i < count($array) / 2; $i++) {
$tmp = $array[$i];
$array[$i] = $array[count($array) -1 - $i];
$array[count($array) - 1 - $i] = $tmp;
}
return $array;
}
$tabToReverse = [5, 8, 95, 10, 6, 17, 42, 20];
echo 'Reversed array : '."\n";
echo implode(' ', reverseArray($tabToReverse));
Run Code Online (Sandbox Code Playgroud)
以下 PHP 代码将比较两个执行(加上一个有语法错误的执行):
<?php
/**
* Run code using eval
*/
$start = microtime(true);
$code = str_replace('<?php', '', file_get_contents('./reverseArray.php'));
echo eval($code)."\n";
$end = microtime(true);
$duration = $end - $start;
echo "Duration using eval $duration\n";
/**
* Run code using container
*/
$start = microtime(true);
$cmd = 'docker run -v "$PWD":/usr/src -w /usr/src --rm php:7.4.5 php ./reverseArray.php';
exec($cmd, $result);
echo implode("\n", $result)."\n";
$end = microtime(true);
$duration = $end - $start;
echo "Duration using container $duration\n";
/**
* Run code using container with an error
*/
$start = microtime(true);
$cmd = 'docker run -v "$PWD":/usr/src -w /usr/src --rm php:7.4.5 php ./reverseArrayWithError.php';
exec($cmd, $resultWithError);
echo implode("\n", $resultWithError)."\n";
$end = microtime(true);
$duration = $end - $start;
echo "Duration using container $duration\n";
Run Code Online (Sandbox Code Playgroud)
我的笔记本电脑上的结果是:
php ./runCode.php
Reversed array :
20 42 17 6 10 95 8 5
Duration using eval 0.00031089782714844
Reversed array :
20 42 17 6 10 95 8 5
Duration using container 0.79519391059875
Parse error: syntax error, unexpected ':', expecting ')' in /usr/src/reverseArrayWithError.php on line 3
Duration using container 0.81346988677979
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,运行容器需要时间。但代码已经在特定区域执行了。
在所有情况下,前端部分都是相同的,它将使用一些 Ajax 查询来将数据 POST 到服务器上,等待结果并显示它。
注 1:即使代码在特定容器中执行,也必须先进行清理,因为用户输入永远不应该被信任。
注2:使用此架构需要管理正在运行的容器以防止过载。如果 10 000 个用户同时提交代码会发生什么?但我认为这是另一个话题。
| 归档时间: |
|
| 查看次数: |
486 次 |
| 最近记录: |