在 symfony 8.2 中,限制表达式引擎读取的常量主要通过配置 `expressionlanguage` 服务并设置 `allowed_functions` 或自定义函数来实现,因为默认情况下它不直接暴露 php 全局常量供任意读取,但可以通过注册自定义函数来安全地访问特定常量。具体做法是创建一个服务提供者或使用编译器 pass 来修改 `expressionlanguage` 实例,仅注册你希望暴露的常量作为只读函数,从而防止未授权的常量访问。

如何配置 ExpressionLanguage 以限制常量访问
要限制常量访问,你需要在 Symfony 的服务容器中定义一个自定义的 `ExpressionLanguage` 服务,并通过注入的 `FunctionProviderInterface` 实现来显式列出允许的常量。默认情况下,Symfony 的表达式引擎不会自动暴露所有 PHP 常量,因此你需要手动注册那些你希望允许在模板或业务逻辑中使用的常量,例如 `APP_ENV` 或 `KERNEL_CLASS`。

namespace App\Service;
use Symfony\Component\ExpressionLanguage\FunctionProviderInterface;
use Symfony\Component\ExpressionLanguage\SyntaxNode;
use Symfony\Component\ExpressionLanguage\Token;
class ConstantFunctionProvider implements FunctionProviderInterface
{
public function getFunctions(): array
{
return [
'get_constant' => new \Symfony\Component\ExpressionLanguage\Node\FunctionNode(
'get_constant',
[new SyntaxNode(new Token('name_token', 'CONST_NAME', 0)), new SyntaxNode(new Token('default_token', 'DEFAULT_VALUE', 0))]
),
];
}
}
上述代码定义了一个简单的函数提供器,其中 `get_constant` 函数可以接受一个常量名和一个默认值。在实际使用中,你需要在 `services.yaml` 中注册这个提供器,并将其添加到 `ExpressionLanguage` 服务的构造函数参数中。这样,只有明确列出的常量才能被表达式引擎访问,其他常量将被拒绝。
如何在控制器中使用受限的常量
在控制器中,你可以注入 `ExpressionLanguage` 服务并使用它来评估表达式。由于我们已经限制了可访问的常量,因此在表达式中只能使用通过 `ConstantFunctionProvider` 注册的常量。这确保了安全性,防止了未授权的常量读取。

namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\HttpFoundation\Response;
use App\Service\ConstantFunctionProvider;
class DefaultController extends AbstractController
{
private $expressionLanguage;
public function __construct(ExpressionLanguage $expressionLanguage)
{
$this->expressionLanguage = $expressionLanguage;
}
public function index(): Response
{
// 假设我们只允许访问 APP_ENV 常量
$result = $this->expressionLanguage->evaluate('get_constant("APP_ENV", "dev")');
return new Response('The value of APP_ENV is: ' . $result);
}
}
在这个示例中,`index` 方法使用 `ExpressionLanguage` 来评估一个表达式,该表达式调用 `get_constant` 函数来获取 `APP_ENV` 常量的值。如果 `APP_ENV` 未被注册为允许的常量,表达式将失败或返回默认值。这种方法确保了只有经过授权的常量才能被访问,从而提高了应用程序的安全性。
基于程序中某个输入、条件或结果的具体问题
如果在表达式中尝试访问未注册的常量,例如 `get_constant("SOME_UNREGISTERED_CONSTANT")`,表达式引擎将抛出异常或返回默认值(如果提供了默认值)。这是预期的行为,因为它确保了未授权的常量不会被意外访问。开发者应确保所有需要访问的常量都在 `ConstantFunctionProvider` 中正确注册,以避免运行时错误。











