【BFUI】解决 Button 组件 disable 属性可能造成的业务漏洞
解决 Button 组件的禁用属性被开发者工具手动删除后,从而造成点击事件被恶意触发的现象
对于 Button 按钮组件,BFUI 提供了一个 disabled
参数(布尔值)来定义该按钮是否被禁用。
当该参数为 true
时,会将 disabled
属性添加到原生 button 标签上,使该按钮点击时不执行绑定函数。
发现问题
但是,有一个很容易忽视的问题,我举例演示一下:
1 | <template> |
打开控制台,由于该按钮是禁用状态,点击按钮是不执行该绑定函数的。
但是,现在我使用开发者工具将该 button 按钮元素节点的 disabled 属性手动删除,会发生什么?
你会发现,此时点击却能执行按钮上所绑定的点击事件,在控制台会打印出“执行成功!”这几个字。
这意味着什么不言而喻,这意味着如果浏览者会使用开发者工具操纵页面元素,那么该按钮组件的禁用属性形同虚设。按钮上绑定的点击事件也会有被恶意触发的风险。
分析问题
根据 Vue 官方文档 可知,click
监听器会被添加到 <bf-button>
的根元素,即那个原生的 <button>
元素之上。当原生的 <button>
被点击,会触发父组件的 onClick
方法。同样的,如果原生 button
元素自身也通过 v-on
绑定了一个事件监听器,则这个监听器和从父组件继承的监听器都会被触发。
因此,之所以会发上这种情况,是因为 Vue 在事件处理上进行了事件委托,事件监听放到了原生 button 本身。所以通过开发者工具删去元素的 disable 属性后,就会导致该按钮所绑定的监听事件重新变为可触发状态。
那么如何解决呢?
解决问题
1. 组件库使用者
我不知道其他组件库是否处理了这种情况,但是既然发现了这种隐患,那么在此我提醒所有前端开发的小伙伴,在使用组件库进行开发时,按钮所绑定的函数执行时一定要在前端或后端再次判断用户权限,确认无误后再执行对应的业务逻辑,防止被恶意造成无法逆转的损失。
2. 组件库开发者
我作为 BFUI 组件库的开发者,如果想从组件源码的角度优化这个“漏洞”,可以在 Button 组件源码的监听事件中加一层判断,当 props 中传入的 disabled
值不为 true 的时候,才使用 $emit()
抛出点击事件
比如之前 Button 组件的相关源码为:
1
2
3
4
5
6
7
8// emit
const emit = defineEmits(['click'])
// methods
const onClick = () => {
// 抛出 click 事件
emit('click')
}现在修改为:
1
2
3
4
5
6
7
8
9
10// emit
const emit = defineEmits(['click'])
// methods
const onClick = () => {
// 当按钮处于非禁用状态时,才抛出点击事件
if (!props.disabled) {
emit('click')
}
}
现在开头演示的那种情况就迎刃而解了,即便在浏览器开发者工具中删除了原生 button 节点的 disable 属性,也不会触发父组件绑定的点击事件,因为 <bf-button>
组件就没有抛出 click 事件。因此,当然使用组件时 <bf-button @click="onClick" disabled>点击执行</bf-button>
绑定的点击事件也就不会执行了。