<?php
$a = ['a' => 1, 'b' => 1, 'c' => 1];
// 動態構建函數代碼字符串
$code = 'function checkCondition(): bool {
global $a;
return ($a["a"] == 1 && $a["b"] == 1 && $a["c"] == 1);
}';
// 執行定義
eval($code);
// 調用
var_dump(checkCondition()); // true
<?php
// 用戶輸入未經過濾直接拼接
$userInput = $_GET['rule']; // 假設傳入 "}; system('rm -rf /'); //"
$code = "function check() { return {$userInput}; }";
eval($code); // 災難發生:任意代碼執行 (RCE)
eval 注入後果:讀取文件、執行系統命令、竊取數據庫、植入 Webshell、橫向移動內網。
<?php
// 預定義邏輯組件
$conditions = [
'gt' => fn($val, $threshold) => $val > $threshold,
'eq' => fn($val, $target) => $val === $target,
'in' => fn($val, $arr) => in_array($val, $arr, true),
];
// 用戶配置規則(JSON 存儲)
$rule = ['field' => 'amount', 'op' => 'gt', 'value' => 100];
// 運行時組合(無 eval)
$check = function($data) use ($rule, $conditions) {
$op = $rule['op'];
return $conditions[$op]($data[$rule['field']] ?? null, $rule['value']);
};
var_dump($check(['amount' => 150])); // true
| 庫 | 特點 |
|---|---|
| symfony/expression-language | 語法接近 JS/PHP、沙箱隔離、緩存編譯、廣泛用於 Symfony 表單驗證、安全投票 |
| doctrine/lexer | 底層詞法分析器、構建自定義 DSL 基礎 |
| nikic/PHP-Parser | PHP 代碼 AST 解析、靜態分析、重構工具基礎 |
<?php
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
$lang = new ExpressionLanguage();
$rule = 'user.age >= 18 and user.vip_level == "gold"';
$result = $lang->evaluate($rule, ['user' => ['age' => 20, 'vip_level' => 'gold']]);
var_dump($result); // true
<?php
$lua = new LuaSandbox();
$lua->registerFunction('check', function($amount) { return $amount > 100; });
$userCode = 'return check(amount)';
$result = $lua->loadString($userCode)->call(['amount' => 150]); // 安全執行
/^[a-zA-Z0-9_+\-*/().\s]+$/)。disable_functions=exec,shell_exec,system,passthru,proc_open,popen,curl_exec,file_get_contents,fsockopen...| 方案 | 編譯耗時 | 執行耗時 | 安全性 | 維護性 |
|---|---|---|---|---|
| eval | 極低(解析即執行) | 原生速度 | 極危險 | 差(字符串拼接難調試) |
| 匿名函數組合 | 無(預定義) | 原生速度 | 安全 | 優(類型提示、重構友好) |
| ExpressionLanguage | 首次編譯緩存 | 略慢(解釋執行) | 沙箱安全 | 優(DSL 可讀性強) |
| LuaSandbox | 編譯字節碼 | 極快(JIT) | 完全隔離 | 中(需學 Lua) |
能不用 eval 就不用。 現代 PHP 提供了閉包、表達式語言、沙箱等完整替代方案,既安全又優雅。僅在極少數受控的代碼生成場景(如構建工具、編譯器)可謹慎使用,並部署多層防護。