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 文本的安全渲染问题。
关于 Web 应用安全有一个准则:永远不要相信用户输入的东西,这里也不例外,提交到数据库的 Markdown 文本很有可能包含恶意代码执行 XSS 攻击,而且我们也不能直接将 Markdown 文本直接渲染到页面给其他用户看,那样会让用户不明所以。这里,学院君引入了一个扩展包 erusev/parsedown 来解决 Markdown 文本的安全渲染问题。
首先还是通过 Composer 来安装这个扩展包:
composer require erusev/parsedown
下载好了之后需要全局引用 Parsedown.php
文件,我们通过 Composer 来实现,编辑 composer.json
,在 autoload
子配置项 files
中添加如下这行配置:
这样我们就可以通过这个扩展包提供的 ParseDown
类进行 Markdown 文本解析了,学院君新增了一个全局的辅助函数 convert_markdown_to_html
来实现解析:
function convert_markdown_to_html($content) {
$parser = new Parsedown();
$parser->setSafeMode(true);
return $parser->parse($content);
}
需要注意的是我这里是将原生的 Markdown 文本保存到数据库,在渲染时进行解析,这样做的好处是方便后续对 Markdown 文本进行编辑,为了性能起见,你可以将解析后的文本缓存起来,直到文本有新的变动再更新缓存。
至此,关于新版学院内容编辑和渲染就告一段落了,学院君这里抛砖引玉,讲了大概的实现思路,具体的细节你可以自己去实现下,有什么问题欢迎在下面的评论框中与我交流。
5 条评论
学院君,请问您,markdown 高亮如何显示的呢? 我的代码块没有颜色,很是......
参考Markdown文档:http://xianbai.me/learn-md/article/extension/code-blocks-and-highlighting.html 具体样式还要结合前端CSS代码
关于xss 问题,erusev/parsedown 可以过滤,但是标签也会直接输出,有没有办法去掉标签,留下字呢?
转化为html后就可以基于 HTML Purifier 进行处理了
赞,非常感谢