事情是这样的:
之前在论坛看到有个网页点击大挑战,破解脚本触发click事件isTrust为false的问题
@cxxjackie 大佬提供思路利用劫持addEventListener,再用Proxy伪装
于是我尝试了下在实际项目里面封装并使用,但是遇到了一个让我匪夷所思的问题
const arrClickDoms = [];
const fakeClickEvent = {
isTrusted: true,
pointerType: "mouse",
};
const ael = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function () {
if (arguments[0] === "click") {
if (arrClickDoms.includes(this)) {
const fn = arguments[1];
arguments[1] = (e) =>
fn.call(
this,
new Proxy(e, {
get: (target, property, receiver) =>
property in fakeClickEvent
? fakeClickEvent[property]
: Reflect.get(target, property, receiver),
})
);
}
}
return ael.apply(this, arguments);
};
//下一次点击事件 随机1-3秒
var nextClick = function (
selector,
{ minNum = 1000, maxNum = 3000 } = {}
) {
return new Promise((reslove, reject) => {
setTimeout(async () => {
try {
const [btn] = await $.get(selector);
if (!arrClickDoms.includes(btn)) {
arrClickDoms.push(btn);
}
btn.click();
arrClickDoms.splice(arrClickDoms.indexOf(btn), 1);
reslove(btn);
} catch (err) {
reject(err);
}
}, cb_randomNum(minNum, maxNum));
});
};
正常来说,有以下几个步骤:
1 先劫持 addEventListener ,
2 调用nextClick 筛选btn元素,将其加入arrClickDoms数组
3 触发btn的click
4 进入劫持后的 addEddEventListener 回调方法 判断btn是否在 arrClickDoms中,如果存在,则返回伪造Proxy,否则直接正常返回
如果是在小demo中,以上封装是没问题,
但是在实际复杂项目场景的时候,却遇到很奇怪的问题
在没有触发 第2步和第3步的时候,直接先执行了第1步和第4步, 再调用click的时候,却不进入 addEddEventListener 回调。
甚至不调用nextClick,也会执行第1步和第4步,
这是反扒机制还是啥的,感觉有点颠覆了我对js的理解机制