Menu

101.XSS 过滤

本节说明

  • 对应视频教程第 101 小节:Sanitizing is a Must

本节内容

本节我们来完成最后一个功能点:防止 XSS 安全漏洞。我们依然从建立测试开始,我们对话题与回复均进行 XSS 过滤,所以我们新建两个测试:
forum\tests\Unit\ThreadTest.php

    .
    .
    /** @test */
    public function a_thread_body_is_sanitized_automatically()
    {
        $thread = create('App\Thread',['body' => "<script>alert('bad')</script><p>This is OK.</p>"]);

        $this->assertEquals("<p>This is OK.</p>",$thread->body);
    }
}

forum\tests\Unit\ReplyTest.php

    .
    .
    /** @test */
    public function a_reply_body_is_sanitized_automatically()
    {
        $reply = create('App\Thread',['body' => "<script>alert('bad')</script><p>This is OK.</p>"]);

        $this->assertEquals("<p>This is OK.</p>",$reply->body);
    }
}

我们借助 HTMLPurifier for Laravel 来过滤 XSS 攻击。首先我们进行安装:

$ composer require "mews/purifier:~2.0"

接着我们进行配置:

$ php artisan vendor:publish --provider="Mews\Purifier\PurifierServiceProvider"

将配置信息替换为以下:
config/purifier.php

<?php

return [
    'encoding'      => 'UTF-8',
    'finalize'      => true,
    'cachePath'     => storage_path('app/purifier'),
    'cacheFileMode' => 0755,
    'settings'      => [
        'thread_or_reply_body' => [
            'HTML.Doctype'             => 'XHTML 1.0 Transitional',
            'HTML.Allowed'             => 'div,b,strong,i,em,a[href|title],ul,ol,ol[start],li,p[style],br,span[style],img[width|height|alt|src],*[style|class],pre,hr,code,h2,h3,h4,h5,h6,blockquote,del,table,thead,tbody,tr,th,td',
            'CSS.AllowedProperties'    => 'font,font-size,font-weight,font-style,margin,width,height,font-family,text-decoration,padding-left,color,background-color,text-align',
            'AutoFormat.AutoParagraph' => true,
            'AutoFormat.RemoveEmpty'   => true,
        ],
    ],
];

配置里的thread_or_reply_body是我们为话题内容定制的,配合 clean() 方法使用:

$thread->body = clean($thread->body, 'thread_or_reply_body');

我们对话题和回复的body属性进行过滤:
forum\app\Thread.php

    .
    .
    protected static function boot()
    {
        parent::boot();

        static::deleting(function ($thread) {
            $thread->replies->each->delete();
        });

        static::created(function ($thread) {
           $thread->update([
               'slug' => $thread->title,
               'body' => clean($thread->body,'thread_or_reply_body')
           ]);
        });
    }
    .
    .

forum\app\Reply.php

    .
    .
    protected static function boot()
    {
        parent::boot(); //

        static::created(function ($reply){
           $reply->thread->increment('replies_count');
           $reply->body = clean($reply->body,'thread_or_reply_body');
        });
        .
        .
    }
    .
    .

我们来运行测试:
file

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~