产品经理:前端实现网页防篡改,你会怎么做?
公众号:程序员白特,欢迎一起交流学习~
如果产品经理要求系统中某个页面的输入框做防止篡改处理,你会怎么做呢?
需求梳理
- 首先,什么是防篡改?
- 简单来说,就是用户输入
input
框值,我们传给后端的值就是用户输入的
- 简单来说,就是用户输入
- 正常情况下用户输入
input
框值,就是我们传递给后端的值,但是部分浏览器插件或者恶意脚本会更改用户输入的值- 常见针对的是输入的钱包地址,我们需要防范被浏览器插件和恶意脚本更改
- 因为实现的效果需要对已有的业务无任何侵入性,保证原有业务的正常运行
- 这里的需求背景在nuxt2技术栈
最终效果
- 业务方只需要加上这个指令就可以
实现思路
- 我们如何保证对原有的代码没有侵入性,保证不影响原有的功能? 对此我们想到一个自定义指令,在指令里面操作。 但是一般指令都是直接写在组件里面的,并不是写在真实的
input
标签上,对此,我们要变更我们的指令,让其去找到真正的input
标签。
// 通常情况下, 这是一个Input组件,我们需要给这个指令找到其真正的 input 标签
<Input v-xxx/>
- 这里的代码实现的是如何找到真实的
input
标签。
-
如何在指令里面发送请求给后端? 对此,我们在指令里面使用自定义事件,让真实的
input
标签绑定上自定义事件 -
里面涉及2个知识点
- 如何给绑定过的
input
标签解绑事件? - 如何在指令里面调用请求的方法
- 如何给绑定过的
-
问题1答案,我们在指令的节点
node
, 在vnode
绑定上一个自定义函数,此自定义函数在解绑事件的时候在调用 -
问题2答案,我们在
vnode.context
调用自定义方法tamperFn\(\)
; 这里的vnode.context
就是this
,相当于我们调用了this.tamperFn\(\)
; 此处的this
就是Vue
实例 (在下面的代码事例中有个属性 isTrusted 至关重要)
- 至此,我们已经实现如何不侵入业务的情况下找到 input 标签 & 如何在 找到的 input 标签绑定事件并且发送请求出去 & 解绑事件 (有个核心问题,到目前为止没有看到如何区分提交的表单数据是用户写的还是被浏览器插件恶意改的,且继续往下看)
js
的event
有个属性isTrusted
- 首先要对所有的
input
标签使用Object.getOwnPropertyDescriptor
进行劫持,找到input
标签的set
属性,此时,当变更input
的输入值我们都可以监控到变化,当有js
变更input
输入框的值都会触发set
方法。
- 上述的功能代码是一个完整的
config.js
, 启动项目的时候直接在nuxt.config.js
加载这个config.js
即可,业务团队使用一个指令即可完成需求。
总结
我们来梳理下流程:
- 首先使用
Object.getOwnPropertyDescriptor
进行劫持所有的input
标签, 在里面会触发自定义事件dispatchTamper
- 自定义事件绑定在真实的
input
标签上,在浏览器执行js
阶段完成了绑定事件。 通过vnode.context
我们可以调用Vue.prototype.tamperFn
方法。 在tamperFn
里面拿到isTrusted
来区分是不是被篡改的值。 - 我们在绑定
input
标签的事情同时,设置了node.cusFn = cusFn
, 用来解绑事件。