Laravel 学院文本编辑器及 XSS 攻击防范 —— Markdown 编辑器篇

作为程序员群体,可能更偏爱使用 Markdown 来编辑文本,学院君也是其中的一员,我平时写文章、周报、技术方案和文档基本都是在 MWeb (Mac系统下一款值得推荐的 Markdown 编辑器)中完成,所以学院里自然也不能少了对 Markdown 编辑器的支持,目前学院发布主题支持富文本编辑器和 Markdown 编辑器二选一,发布评论为了简单起见,只支持 Markdown:

主题编辑器页面

评论编辑器页面

和富文本编辑器不一样,Markdown 编辑器不支持所见即所得,所以提供了预览按钮方便在发布之前查看效果。

这里学院君以主题发布与编辑为例,演示下 Markdown 编辑器的实现、Markdown 文本的预览和渲染以及如何防范 XSS 攻击。

为了简单起见,学院的 Markdown 编辑器直接使用原生的 textarea 输入框,当然如果你追求更酷的效果的话,可以去选择类似富文本编辑器的输入框,后面学院可能也会对 Markdown 编辑器进行升级:

<!--输入部分-->
<textarea class="form-control" id="markdown-area" rows="20">
    {{ $article->content }}
</textarea> 
...
<!--预览部分-->
<div class="content-preview-area" style="display: none;">

预览功能的实现通过前端 JavaScript 库 markdown-it 来实现,使用之前需要通过引入相应的库文件:

<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/8.4.2/markdown-it.min.js"></script>

然后通过监听预览按钮点击事件实现前端预览功能:

jQuery('#post-preview').on('click', function () {
    var md = window.markdownit();
    var result = md.render(jQuery('#markdown-area').val());
    jQuery('.content-preview-area').html(result);
    jQuery('.content-preview-area').show();
});

下面是编辑与预览效果示例:

Markdown编辑文本预览效果

这里需要额外声明的就是图片上传问题,你可以将第三方图片以链接的方式拷贝过来,也可以通过页面上的封面图片功能上传图片后将图片链接拷贝过来。

接下来我们来实现 Markdown 文本的安全渲染问题。

关于 Web 应用安全有一个准则:永远不要相信用户输入的东西,这里也不例外,提交到数据库的 Markdown 文本很有可能包含恶意代码执行 XSS 攻击,而且我们也不能直接将 Markdown 文本直接渲染到页面给其他用户看,那样会让用户不明所以。这里,学院君引入了一个扩展包 erusev/parsedown 来解决 Markdown 文本的安全渲染问题。

首先还是通过 Composer 来安装这个扩展包:

composer require erusev/parsedown

下载好了之后需要全局引用 Parsedown.php 文件,我们通过 Composer 来实现,编辑 composer.json,在 autoload 子配置项 files 中添加如下这行配置:

全局引入ParseDown文件

这样我们就可以通过这个扩展包提供的 ParseDown 类进行 Markdown 文本解析了,学院君新增了一个全局的辅助函数 convert_markdown_to_html 来实现解析:

function convert_markdown_to_html($content) {
    $parser = new Parsedown();
    $parser->setSafeMode(true);
    return $parser->parse($content);
}

需要注意的是我这里是将原生的 Markdown 文本保存到数据库,在渲染时进行解析,这样做的好处是方便后续对 Markdown 文本进行编辑,为了性能起见,你可以将解析后的文本缓存起来,直到文本有新的变动再更新缓存。

至此,关于新版学院内容编辑和渲染就告一段落了,学院君这里抛砖引玉,讲了大概的实现思路,具体的细节你可以自己去实现下,有什么问题欢迎在下面的评论框中与我交流。

学院君 has written 1076 articles

Laravel学院院长,终身学习者

积分:134037 等级:P12 职业:手艺人 城市:杭州

5 条回复

  1. hedeqiang hedeqiang says:
    @ 学院君

    关于xss 问题,erusev/parsedown 可以过滤,但是标签也会直接输出,有没有办法去掉标签,留下字呢?

  2. hedeqiang hedeqiang says:

    学院君,请问您,markdown 高亮如何显示的呢? 我的代码块没有颜色,很是......

登录后才能进行评论,立即登录?