intaro / twig-sandbox-bundle
为 Twig_Sandbox 扩展允许的方法和属性进行注解配置
Requires
- php: ^8.1
- doctrine/annotations: ^1.13|^2.0
- psr/cache: ~1.0|~2.0
- symfony/framework-bundle: ^5.0|^6.0
- symfony/validator: ^5.0|^6.0
- twig/twig: ^2.14 | ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3
- nyholm/symfony-bundle-test: ^3.0
- phpstan/phpstan: ^1.0
- phpstan/phpstan-symfony: ^1.0
- phpunit/phpunit: ^8.5|^9.5
- psr/log: ~1.0
- symfony/config: ^5.0|^6.0
- symfony/dependency-injection: ^5.0|^6.0
- symfony/deprecation-contracts: ^1.1|^2.0
- symfony/error-handler: ^5.0|^6.0
- symfony/event-dispatcher: ^5.0|^6.0
- symfony/event-dispatcher-contracts: ^1.1|^2.0
- symfony/filesystem: ^5.0|^6.0
- symfony/finder: ^5.0|^6.0
- symfony/http-foundation: ^5.0|^6.0
- symfony/http-kernel: ^5.0|^6.0
- symfony/phpunit-bridge: ^5.0|^6.0
- symfony/routing: ^5.0|^6.0
- symfony/translation-contracts: ^1.1|^2.0
- symfony/var-dumper: ^5.0|^6.0
- symfony/var-exporter: ^5.0|^6.0
- symfony/yaml: ^5.0|^6.0
README
存在一个 Twig-extension Sandbox,可以用来评估不受信任的代码,其中禁止访问不安全的属性和方法。此包允许配置沙箱的安全策略。
安装
TwigSandboxBundle 需要 Symfony 5.4 或更高版本。
安装此包
$ composer require intaro/twig-sandbox-bundle
在 config/bundles.php
中注册此包
return [ // ... Intaro\TwigSandboxBundle\IntaroTwigSandboxBundle::class => ['all' => true], ];
使用
使用属性 #[Sandbox]
定义实体允许的属性和方法。可选地,您可以添加 type
选项给属性(例如 #[Sandbox(type: 'int')]
)。此选项定义了属性存储的值或方法返回的类型。
在您的应用程序中,您可以使用注解读取器提取 type
选项的值,并使用此值执行额外的检查或任何其他操作,例如,根据选项的值使用 twig 过滤器。
<?php // Acme/DemoBundle/Entity/Product.php namespace Acme\DemoBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Intaro\TwigSandboxBundle\Annotation\Sandbox; #[ORM\Table] #[ORM\Entity] class Product { #[ORM\Column(name: 'id', type: 'integer')] #[ORM\Id] #[ORM\GeneratedValue(strategy: "AUTO")] private ?int $id = null; #[ORM\Column(name: 'name', type: 'string', length: 255)] #[Sandbox(type: 'string')] private string $name = ''; #[ORM\Column(name: 'quantity', type: 'integer', nullable: true)] private ?int $quantity = null; #[Sandbox(type: 'int')] public function getId(): ?int { return $this->id; } public function setName(string $name): self { $this->name = $name; return $this; } #[Sandbox] public function getName(): string { return $this->name; } public function setQuantity(?int $quantity): self { $this->quantity = $quantity; return $this; } public function getQuantity(): ?int { return $this->quantity; } }
并使用沙箱环境。
use Acme\DemoBundle\Entity\Product; use Intaro\TwigSandboxBundle\Builder\EnvironmentBuilder; class Example { private EnvironmentBuilder $environmentBuilder; public function __construct(EnvironmentBuilder $environmentBuilder) { $this->environmentBuilder = $environmentBuilder; } $twig = $this->environmentBuilder->getSandboxEnvironment(); $product = new Product(); $product->setName('Product 1'); $product->setQuantity(5); // successful render $html1 = $twig->render( 'Product {{ product.name }}', ['product' => $product] ); // render with the exception on access to the quantity method $html2 = $twig->render( 'Product {{ product.name }} in the quantity {{ product.quantity }}', ['product' => $product] ); }
验证
您可以使用 TwigSandbox 验证器验证包含 twig 模板的实体字段。
// in Entity/Page.php use Intaro\TwigSandboxBundle\Validator\Constraints\TwigSandbox; class Page { //... public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('template', new TwigSandbox()); } //... }
配置
方法和属性
您可以使用属性 Intaro\TwigSandboxBundle\Attribute\Sandbox
定义实体允许的方法和属性。例如上述代码。
标签
默认允许的标签列表
- 'autoescape' - 'filter' - 'do' - 'flush' - 'for' - 'set' - 'verbatium' - 'if' - 'spaceless'
您可以在参数 intaro.twig_sandbox.policy_tags
中覆盖此列表
# app/config/config.yml parameters: intaro.twig_sandbox.policy_tags: - 'do' - 'for' - 'if' - 'spaceless'
过滤器
默认允许的过滤器列表
- 'abs' - 'batch' - 'capitalize' - 'convert_encoding' - 'date' - 'date_modify' - 'default' - 'escape' - 'first' - 'format' - 'join' - 'json_encode' - 'keys' - 'last' - 'length' - 'lower' - 'merge' - 'nl2br' - 'number_format' - 'raw' - 'replace' - 'reverse' - 'slice' - 'sort' - 'split' - 'striptags' - 'title' - 'trim' - 'upper' - 'url_encode'
您可以在参数 intaro.twig_sandbox.policy_filters
中覆盖此列表
# app/config/config.yml parameters: intaro.twig_sandbox.policy_filters: - 'sort' - 'upper' - 'sort'
函数
默认允许的函数列表
- 'attribute' - 'constant' - 'cycle' - 'date' - 'random' - 'range'
您可以在参数 intaro.twig_sandbox.policy_functions
中覆盖此列表
# app/config/config.yml parameters: intaro.twig_sandbox.policy_functions: - 'date' - 'range'
允许的类型
默认允许的返回类型列表
- 'bool' - 'collection' - 'date' - 'float' - 'int' - 'object' - 'string'
您可以在参数 intaro.twig_sandbox.sandbox_annotation.value_types
中覆盖此列表
# app/config/config.yml parameters: intaro.twig_sandbox.sandbox_annotation.value_types: - 'string' - 'date' - 'collection' - 'stdClass'
环境
您可以设置 twig 环境参数
$twig = $this->get(EnvironmentBuilder::class)->getSandboxEnvironment([ 'strict_variables' => true ]);
此外,您可能还想向 twig 环境添加扩展。以下是如何添加的示例
// Acme/DemoBundle/AcmeDemoBundle.php <?php namespace Acme\DemoBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Acme\DemoBundle\DependencyInjection\Compiler\TwigSandboxPass; class AcmeDemoBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new TwigSandboxPass()); } }
// Acme/DemoBundle/DependencyInjection/Compiler/TwigSandboxPass.php <?php namespace Acme\DemoBundle\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Intaro\TwigSandboxBundle\Builder\EnvironmentBuilder; class TwigSandboxPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { if (!$container->hasDefinition(EnvironmentBuilder::class)) { return; } $sandbox = $container->getDefinition(EnvironmentBuilder::class); $sandbox->addMethodCall('addExtension', [new Reference('acme_demo.twig_extension')]); } }
开发
运行测试
安装依赖
make vendor
运行 php-cs-fixer、phpstan 和 phpunit
make check