在vue开发过程中的一些关于xss与v-html的思考
问题描述
- vue开发中,在一个下拉框中需要将下拉数据中后端返回的html代码效果直接显示在下拉框中
文档:在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用
v-html
,永不用在用户提交的内容上。 - 于是我开始思考,接口返回的内容算可信内容吗?会不会出现接口被截取导致返回内容不可信的情况发生?(事实上是我多虑了…)
- 询问了我的哥哥(后端)以后,得到了靠谱的答案!
结论
- 接口返回的内容可以使用v-html显示。
- 接口返回的内容需要后端做应对xss攻击的安全处理以后才能显示
- 因为 xss 攻击主要是为了获取用户的 cookie 也就是登录身份。攻击者如果都能截取请求返回值了,为什么不直接去取请求里的 cookie 呢?所以基本不用担心攻击者截取接口篡改返回内容。
前端预防XSS
- 当然,如果还是担心,前端也可通过XSS工具替换特殊字符,如
<
变为<;
>
变为>
,<script>
变为<;script>;
直接显示,而不会作为脚本执行 - 前端在显示时替换,后端在存储时替换,都做总不会有错(可参考XSS网络攻击及防范)
vue中使用XSS工具
- 除了XSS工具官网提供的使用方法,还可以通过覆盖html指令实现。引入组件
XSS
,在编译前将从vue-loader
传入的compilerOptions.directives
和baseOptions.directives
进行了合并。- 覆写可以方便的从根本上面解决XSS攻击的问题,不用担心后续其他开发重复操作等问题
- 覆写步骤:
1.npm isntall xss
2.配置文件:3.挂载全局:在1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// @/utils/xss.j
const xss = require('xss')
const options = {
css: false,
onTag(tag, html, options) {
if (tag === 'iframe') {
return html.replace(/javascript:?/, '')
}
},
// 避免把页面样式过滤掉
onIgnoreTagAttr(tag, name, value, isWhiteAttr) {
// 过滤掉标签上的事件
if (/^[^on]/.test(name)) {
return name + '="' + xss.escapeAttrValue(value) + '"'
}
},
}
const filter = new xss.FilterXSS(options)
export default filtermain.js
页面引入(为了在 loader中能够通过该方法过滤全局的v-html
返回数据)4.模块预处理:在1
2import xss from 'xss';
Vue.prototype.xss = xssvue.config.js
中覆写html指令(如果是nuxt.js框架写的就是在nuxt.config.js
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// ...
module.exports = {
// ...
chainWebpack: config => {
// ...
// 增加 xss 处理
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.directives = {
html (node, directiveMeta) {
const props = node.props || (node.props = [])
props.push({
name: 'innerHTML',
value: `$xss.process(_s(${directiveMeta.value}))`,
})
},
}
return options
})
},
}