stevebauman/purify

Laravel 的 HTML 清理/消毒器

v6.2.1 2024-08-26 16:21 UTC

README

A Laravel 的 HTMLPurifier 包装器,由 ezyang 开发 HTMLPurifier

索引

需求

  • PHP >= 7.4
  • Laravel >= 7.0

安装

要在项目中安装 Purify,请在项目根目录下运行以下命令

composer require stevebauman/purify

然后,使用以下命令发布配置文件

php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"

用法

清理字符串

要清理用户输入,只需使用 clean 方法

use Stevebauman\Purify\Facades\Purify;

$input = '<script>alert("Harmful Script");</script> <p style="border:1px solid black" class="text-gray-700">Test</p>';

// Returns '<p>Test</p>'
$cleaned = Purify::clean($input);
清理数组

需要净化用户输入的数组?只需传递一个数组即可

use Stevebauman\Purify\Facades\Purify;

$array = [
    '<script>alert("Harmful Script");</script> <p style="border:1px solid black" class="text-gray-700">Test</p>',
    '<script>alert("Harmful Script");</script> <p style="border:1px solid black" class="text-gray-700">Test</p>',
];

$cleaned = Purify::clean($array);

// array [
//  '<p>Test</p>',
//  '<p>Test</p>',
// ]
var_dump($cleaned);
动态配置

需要为单个输入使用不同的配置?将配置数组传递到第二个参数

注意:传递到第二个参数的配置不会与您的默认配置合并。

use Stevebauman\Purify\Facades\Purify;

$config = ['HTML.Allowed' => 'div,b,a[href]'];

$cleaned = Purify::config($config)->clean($input);

配置

在配置文件中,可以指定多个 HTMLPurifier 配置集,类似于 Laravel 内置的 databasemaillogging 配置。只需调用 Purify::config($name)->clean($input) 来使用另一组配置。

例如,如果我们需要一个单独的配置来为评论系统,我们可以在 config/purify.php 文件中设置此配置

// config/purify.php

'configs' => [
    // ...

    'comments' => [
        // Some configuration ...
    ],
]

然后,通过其名称在任何地方利用它

use Stevebauman\Purify\Facades\Purify;

$cleanedContent = Purify::config('comments')->clean(request('content'));

有关 HTMLPurifier 配置文档,请访问 HTMLPurifier 网站

http://htmlpurifier.org/live/configdoc/plain.html

缓存

运行 Purify 一次后,HTMLPurifier 将自动将您的序列化 definitions 缓存到在 config/purify.php 中配置的 serializer.cache 定义中。

重要

如果您已将 Purify 配置为在 serializer 选项中使用 CacheDefinitionCache,则此命令将在您配置其使用的缓存驱动程序上发出 Cache::clear()

如果您已将 Purify 配置为在 serializer 选项中使用 FilesystemDefinitionCache,则此命令将清除您配置其存储的目录。

如果您打算使用此命令清除序列化定义,建议为 Purify 设置唯一的文件系统路径或磁盘(通过 config/filesystems.php)或缓存存储(通过 config/cache.php)。

如果您更新了 definitions 配置选项,则必须清除此 HTMLPurifier 缓存。

您可以通过 purify:clear 命令这样做

php artisan purify:clear

禁用缓存

要完全禁用缓存,您可以将 serializer 路径设置为 null

// config/purify.php

'serializer' => null,

这将导致您的定义在每个应用程序请求上序列化。

这对于调试或调整定义文件以查看即时结果特别有用。

重要

在生产环境中推荐使用缓存。

实践

如果您正在考虑消毒,您可能希望消毒存储在数据库中的用户 HTML 内容,然后将其渲染到您的应用程序中。

在此场景中,最佳实践可能在输出时进行清理,而不是输入时。数据库对包含的文本内容并不关心。

这样,您可以允许任何内容被插入数据库,并在输出时使用强大的清理规则。

要实现这一点,您可以在Eloquent模型上使用提供的PurifyHtmlOnGet转换类。

use Stevebauman\Purify\Casts\PurifyHtmlOnGet;

class Post extends Model
{
    protected $casts = [
        'content' => PurifyHtmlOnGet::class,
    ];
}

或者,通过Eloquent属性转换器自行实现。

use Stevebauman\Purify\Facades\Purify;

class Post extends Model
{
    public function getContentAttribute($value)
    {
        return Purify::clean($value);
    }
}

您甚至可以通过将配置名称附加到转换来配置用于转换的配置。

// config/purify.php

'configs' => [
    // ...

    'other' => [
        // Some configuration ...
    ],
]
protected $casts = [
    'content' => PurifyHtmlOnGet::class.':other',
];

如果以后更改清理要求,这将非常有帮助,因为所有渲染的内容都将遵循这些清理规则。

如果您在设置值时想清理HTML,可以使用逆转换PurifyHtmlOnSet

自定义HTML定义

HTML.Doctype配置选项表示最终遵守的架构。您可能希望通过指定自定义HTML元素“定义”来扩展这些架构定义以支持自定义元素或属性(例如,<foo>...</foo><span foo="...">)。

Purify提供了HTMLPurifier尚未支持的额外HTML5定义(通过Html5Definition类)。

要创建自己的HTML定义,创建一个新类并使其实现Definition

namespace App;

use HTMLPurifier_HTMLDefinition;
use Stevebauman\Purify\Definitions\Definition;

class CustomDefinition implements Definition
{
    /**
     * Apply rules to the HTML Purifier definition.
     *
     * @param HTMLPurifier_HTMLDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        // Customize the HTML purifier definition.
    }
}

然后,在config/purify.php文件中的definitions键中引用此类。

// config/purify.php

'definitions' => \App\CustomDefinitions::class,

如果您想扩展内置的默认Html5Definition,您可以将它应用到您的自定义定义中。

use Stevebauman\Purify\Definitions\Html5Definition;

class CustomDefinition implements Definition
{
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        Html5Definition::apply($definition);
        
        // ...
    }
}
Basecamp Trix 定义

以下是一个示例,说明如何自定义定义以支持Basecamp的Trix WYSIWYG编辑器(归功于Antonio PrimeraDaniel Sun

namespace App;

use HTMLPurifier_HTMLDefinition;
use Stevebauman\Purify\Definitions\Definition;

class TrixPurifierDefinitions implements Definition
{
    /**
     * Apply rules to the HTML Purifier definition.
     *
     * @param HTMLPurifier_HTMLDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_HTMLDefinition $definition)
    {
        $definition->addElement('figure', 'Inline', 'Inline', 'Common');
        $definition->addAttribute('figure', 'class', 'Class');
        $definition->addAttribute('figure', 'data-trix-attachment', 'Text');
        $definition->addAttribute('figure', 'data-trix-attributes', 'Text');

        $definition->addElement('figcaption', 'Inline', 'Inline', 'Common');
        $definition->addAttribute('figcaption', 'class', 'Class');
        $definition->addAttribute('figcaption', 'data-trix-placeholder', 'Text');

        $definition->addAttribute('a', 'rel', 'Text');
        $definition->addAttribute('a', 'tabindex', 'Text');
        $definition->addAttribute('a', 'contenteditable', 'Enum#true,false');
        $definition->addAttribute('a', 'data-trix-attachment', 'Text');
        $definition->addAttribute('a', 'data-trix-content-type', 'Text');
        $definition->addAttribute('a', 'data-trix-id', 'Number');

        $definition->addElement('span', 'Block', 'Flow', 'Common');
        $definition->addAttribute('span', 'data-trix-cursor-target', 'Enum#right,left');
        $definition->addAttribute('span', 'data-trix-serialize', 'Enum#true,false');

        $definition->addAttribute('img', 'data-trix-mutable', 'Enum#true,false');
        $definition->addAttribute('img', 'data-trix-store-key', 'Text');
    }
}

自定义CSS定义

可以覆盖CSS定义,这允许您自定义允许的行内样式及其属性和值。这可以帮助填充诸如text-align等属性的缺失值,该属性的默认值是缺失开始和结束值。您可以通过创建CSS定义来完成此操作。

要创建自己的CSS定义,创建一个新类并使其实现CssDefinition

namespace App;

use HTMLPurifier_CSSDefinition;
use Stevebauman\Purify\Definitions\CssDefinition;

class CustomCssDefinition implements CssDefinition
{
    /**
     * Apply rules to the CSS Purifier definition.
     *
     * @param HTMLPurifier_CSSDefinition $definition
     *
     * @return void
     */
    public static function apply(HTMLPurifier_CSSDefinition $definition)
    {
        // Customize the CSS purifier definition.
        $definition->info['text-align'] = new \HTMLPurifier_AttrDef_Enum(
            ['right', 'left', 'center', 'start', 'end'],
            false,
        );
    }
}

然后,在config/purify.php文件中的css-definitions键中引用此类。

// config/purify.php

'css-definitions' => \App\CustomCssDefinition::class,

请参阅HTMLPurifier库中的HTMLPurifier_CSSDefinition类以获取其他可以更改的示例。

从 v4 升级到 v5

要从v4升级,请在项目根目录中运行以下命令来安装最新版本

composer require stevebauman/purify

然后,导航到您的已发布config/purify.php配置文件并复制settings数组--除了以下键

  • HTML.DocType:
  • Core.Encoding:
  • Cache.SerializerPath:
'settings' => [
-   'Core.Encoding' => 'utf-8',
-   'Cache.SerializerPath' => storage_path('app/purify'),
-   'HTML.Doctype' => 'XHTML 1.0 Strict',
+   'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
+   'HTML.ForbiddenElements' => '',
+   'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
+   'AutoFormat.AutoParagraph' => false,
+   'AutoFormat.RemoveEmpty' => false,
],

重要:如果您已为Cache.SerializerPath创建唯一的存储路径,请注意这一点,以便您可以将其迁移到新的配置文件。

复制后,删除config/purify.php文件,并运行以下命令

php artisan vendor:publish --provider="Stevebauman\Purify\PurifyServiceProvider"

然后,在新的config/purify.php配置文件中,将键粘贴到(覆盖当前)configs.default数组中

'configs' => [
    'default' => [
        'Core.Encoding' => 'utf-8',
        'HTML.Doctype' => 'HTML 4.01 Transitional',
+       'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
+       'HTML.ForbiddenElements' => '',
+       'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
+       'AutoFormat.AutoParagraph' => false,
+       'AutoFormat.RemoveEmpty' => false,
    ],
],

如果您已创建唯一的序列化器路径(以前通过上述旧的Cache.SerializerPath配置键设置),则可以在新的serializer配置键中重新配置此路径。

'serializer' => storage_path('app/purify'),

一切就绪!

从 v5 升级到 v6

在v6中,HTMLPurifier序列化器存储机制已更新以支持Laravel Vapour,允许您将序列化的HTMLPurifier定义存储在Redis缓存或外部文件系统中。

要从v5版本升级,请在项目的根目录下运行以下命令以安装最新版本

composer require stevebauman/purify

然后,进入您发布的 config/purify.php 配置文件,并将 serializer 配置选项替换为以下内容

-    'serializer' => storage_path('app/purify'),

+    'serializer' => [
+       'disk' => env('FILESYSTEM_DISK', 'local'),
+       'path' => 'purify',
+       'cache' => \Stevebauman\Purify\Cache\FilesystemDefinitionCache::class,
+    ],
+
+    // 'serializer' => [
+    //    'driver' => env('CACHE_DRIVER', 'file'),
+    //    'cache' => \Stevebauman\Purify\Cache\CacheDefinitionCache::class,
+    // ],

这将更新控制序列化器缓存机制的语法。如果您想使用 Laravel 缓存驱动器(如 Redis)来存储序列化定义,现在可以取消注释下面的 serializer 缓存定义。