如何渲染带链接的用户帖子并过滤其余用户输入的HTML内容
回答
你之前的服务端渲染方案出安全问题,核心是处理顺序错了,不是服务端渲染思路本身不可行。
Go服务端安全渲染实现方式
你之前把拼接完mention标签的内容直接转成template.HTML传给模板,等于主动告知模板引擎“这段内容是安全的,不需要转义”,用户输入的恶意HTML、脚本自然会被直接解析执行,按以下顺序处理就能兼顾功能和安全:
- 第一步:先对用户提交的原始帖子内容做全量HTML转义,把
<、>、&、单双引号这类特殊字符全部转成对应的HTML实体,这一步做完之后,用户输入的任何HTML、脚本代码都会变成纯文本展示,完全无法被浏览器解析。Go标准库自带的html.EscapeString()方法可以直接完成转义,不用自己手写规则。 - 第二步:在转义后的文本基础上,用正则匹配
@username格式的提及内容(正则可以根据你站点的用户名规则调整,比如通用的@([a-zA-Z0-9_]+)),把匹配到的用户名替换成你需要的HTML结构,比如跳转到用户主页的a标签。 - 第三步:处理完成的内容再作为
template.HTML类型传入模板渲染即可。这时候内容里只有你自己拼接的a标签是可信HTML,所有用户输入的内容都已经被转义,不存在注入风险。
注意:绝对不能调换转义和替换mention的顺序,要是先替换标签再转义,你自己拼接的a标签也会被转成普通文本,功能直接失效。
客户端JS处理方案的优劣势
客户端处理mention没有绝对的好坏,结合实际场景选择即可,核心注意点和优劣势如下:
- 优势:服务端只需要存储用户提交的原始纯文本,不需要提前拼接HTML,后续如果要调整mention的跳转路径、展示样式,直接改前端代码就能对所有历史帖子生效,不需要批量处理存量数据。
- 必守的安全规则:客户端处理绝对不能跳过转义。不管JS逻辑怎么写,绝对不能把用户提交的原始内容直接通过
innerHTML插入页面。正确做法是先把纯文本通过textContent赋值给DOM节点(这一步浏览器会自动完成转义),再匹配文本节点里的@mention替换成链接元素;如果是前端拼接HTML字符串,也必须先转义用户内容再拼接自定义标签,否则一样会触发XSS漏洞。
实际生产环境更推荐客户端处理的方案,前后端职责更清晰:服务端只负责存储、返回纯文本内容,所有格式渲染逻辑收敛在前端,能大幅降低服务端渲染时因逻辑疏漏引发安全问题的概率。
内容的提问来源于stack exchange,提问作者hermancain
相关产品推荐
相关产品推荐

