回复内容过滤 XSS 后内容为空时,使用更加友好的处理方式

为了对回复内容进行 XSS 过滤,教程中是通过在模型监控器 ReplyObserver 中监控 created 事件来实现,但是这就会造成一个问题:当过滤后的内容为空时,依旧将空内容的回复插入到数据库中,其实这是有问题的。
file

我的想法是在控制器里进行 XSS 过滤,并对过滤结果进行判断,代码如下:

public function store(ReplyRequest $request, Reply $reply)
{
        // XSS 过滤
        $content = clean($request->get('content'));
        if (empty($content)) {
            return redirect()->back()->with('error', '回复内容错误!');
        }

        $reply->content = $content;
        $reply->user_id = Auth::id();
        $reply->topic_id = $request->get('topic_id');
        $reply->save();

        return redirect($reply->topic->link())->with('success', '创建成功!');
}
Make it run, make it right, make it fast.
本帖已被设为精华帖!
本帖由系统于 3年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 18

哥,别人攻击你,你还给他一个友好的提示?

6年前 评论

小小的更改一下,这里的错误返回信息将error改为denger,无需更改其它部分代码。页面报错部分为红色醒目。


        $content = clean($request->get('content'));
        if (empty($content)) {
            return redirect()->back()->with('danger', '回复内容错误!');
        }

file

5年前 评论

@Elinger 友好的提示不重要 重要的是 别人可以往你的回复里发布空内容了

5年前 评论
ZsmHub

xss 过滤后内容为空时,确实不应该保存进我们的数据库。

我的处理方案如下:

class ReplyObserver
{
    public function saving(Reply $reply)
    {
        // xss 过滤
        $reply->content = clean($reply->content, 'default');

        // 判断内容为空的处理方式,拒绝保存入库
        if ($reply->content === '') {
            return false;
        }
    }
}

class RepliesController extends Controller
{
    public function store(ReplyRequest $request, Reply $reply)
    {
        $reply->content = $request->content;
        $reply->user_id = Auth::id();
        $reply->topic_id = $request->topic_id;
        $ret = $reply->save();

        // xss 过滤后回复内容为空,则评论创建失败
        if (!$ret) {
            return redirect()->to($reply->topic->link())->with('danger', '评论创建失败!');
        }

        return redirect()->to($reply->topic->link())->with('success', '评论创建成功!');
    }
}
4年前 评论
rabbit_wl 3年前
kakaxi 2年前

哥,别人攻击你,你还给他一个友好的提示?

6年前 评论

@Elinger 友好的提示不重要 重要的是 别人可以往你的回复里发布空内容了

5年前 评论

这个想法很有意义,可以防止往数据库中插入内容为空的回复。

5年前 评论

不是有这个么?

public function rules()
    {
        return [
            'content' => 'required|min:2',
        ];
    }
5年前 评论
_mars 4年前

@FakeSPrite 是 XSS 过滤之后内容为空了

5年前 评论

小小的更改一下,这里的错误返回信息将error改为denger,无需更改其它部分代码。页面报错部分为红色醒目。


        $content = clean($request->get('content'));
        if (empty($content)) {
            return redirect()->back()->with('danger', '回复内容错误!');
        }

file

5年前 评论

个人觉得 这个没有什么意义 第一如果有人插入这样的内容说明是有意而为之 不需要警告任何东西 就好比被404 因为是错误操作所以不需要告诉你任何东西 直接粗暴的404 还有一点就是 如果想做的话 建议 最好不要在控制器里 去做这些事情 laravel 加了observer 等等这些东西 就是想让应该完成的功能在应该的地方完成 其实这些功能都可以在控制器中完成 不过那样就相当的麻烦 所以我认为在学习完laravel 之前 最好跟着作者的方式走! 把实现的功能放到它应该所在的位置上!

5年前 评论

是否可以直接通过e函数 直接处理了 ?

4年前 评论
ZsmHub

xss 过滤后内容为空时,确实不应该保存进我们的数据库。

我的处理方案如下:

class ReplyObserver
{
    public function saving(Reply $reply)
    {
        // xss 过滤
        $reply->content = clean($reply->content, 'default');

        // 判断内容为空的处理方式,拒绝保存入库
        if ($reply->content === '') {
            return false;
        }
    }
}

class RepliesController extends Controller
{
    public function store(ReplyRequest $request, Reply $reply)
    {
        $reply->content = $request->content;
        $reply->user_id = Auth::id();
        $reply->topic_id = $request->topic_id;
        $ret = $reply->save();

        // xss 过滤后回复内容为空,则评论创建失败
        if (!$ret) {
            return redirect()->to($reply->topic->link())->with('danger', '评论创建失败!');
        }

        return redirect()->to($reply->topic->link())->with('success', '评论创建成功!');
    }
}
4年前 评论
rabbit_wl 3年前
kakaxi 2年前

按作者的方式更好

4年前 评论
DuJianjun 4年前

以上老哥代码的完善,还可以再完善,但是我是菜鸟,就不深入了

【1】修改config/purifier.php

<?php

return [
    'encoding'      => 'UTF-8',
    'finalize'      => true,
    'cachePath'     => storage_path('app/purifier'),
    'cacheFileMode' => 0755,
    'settings'      => [
        'user_topic_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,
        ],
        'user_reply_body' => [
            'HTML.Doctype'             => 'XHTML 1.0 Transitional',
            'HTML.Allowed'             => '',
            'CSS.AllowedProperties'    => '',
            'AutoFormat.AutoParagraph' => false,
            'AutoFormat.RemoveEmpty'   => true,
        ],
    ],
];

【2】ReplyObserve.php文件修改

public function saving(Reply $reply)
    {
        $reply->content = clean($reply->content, 'user_reply_body');
        #dump($reply->content);
        #dd($reply->content);
        if(mb_strlen($reply->content) < 2)
        {
            return false;
        }
    }
2年前 评论

如果回复真的只是要讨论代码, 这么做会好一点

$reply->content = htmlspecialchars($request->content);

2年前 评论
public function creating(Reply $reply)
{
    if(clean($reply->content, 'user_topic_body') == null)
        {
            session()->flash('danger', '评论失败,请勿提交危险代码.');
            return false;
        }else{
        session()->flash('success', '评论成功!');
        $reply->content = clean($reply->content, 'user_topic_body');
    }
}

小弟是这么写的,再把store里面的with方法去掉就OK了.

2年前 评论
DogLoML

不如直接搞个中间件专门过滤xss,不然这里有危险,这里加一段,那里有危险,那里又加一段,重复率很高。中间件里面检测到xss提交,直接显示非法输入就行了。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!