回复内容过滤 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年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 18

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

5年前 评论

小小的更改一下,这里的错误返回信息将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 2年前
kakaxi 2年前

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

5年前 评论

@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 2年前
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年前 评论

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