intaro/twig-sandbox-bundle

为 Twig_Sandbox 扩展允许的方法和属性进行注解配置

安装次数: 384,402

依赖关系: 0

建议者: 0

安全性: 0

星标: 6

关注者: 6

分支: 6

开放问题: 1

类型:symfony-bundle

v3.0.0 2024-09-16 13:23 UTC

README

CI

存在一个 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