警告:该随笔内容仅用于合法范围下的浏览,不得用于任何商业和非法用途,不得未经授权转载,否则后果自负,我一定会用我折腾js的精力向你索赔到底!
首先,这个帖子里的内容仅供某星官方内部人员参考研究学习来完善其代码缺陷,因此我不提倡任何与此无关者使用我的代码、方法和思路,否则产生的一切后果请您自负,本人概不负责。如果继续往下读,我视为您已读到这里并同意我的条件。
最近闲来无事决定研究一下某星的禁止粘贴功能。
首先有一个公认的新手级的化解办法,就是直接F12手动修改html源代码,是个人都可以用这个办法强行粘贴。(但是道高一尺魔高一丈,如果某星实现了像这个网页https://www.aqistudy.cn/historydata/daydata.php?city=%E5%8C%97%E4%BA%AC的能力,我现在就无可奈何了,它不仅可以阻止你在页面加载好后打开控制台,而且还可以随时检测到打开控制台并予以制裁)
但我还是喜欢再多研究一下。
1、如果打开控制台,再尝试直接用鼠标右键粘贴,会出现一些死机的情况,同时会不停跳出debugger的提示,源于一个4000ms的setInterval定时器。我尝试过一些禁止断点、设置条件断点为条件false、使用for循环清空所有setInterval定时器等各种方法,最后面临的无非还是失败,以及无限的死机。最后忍无可忍,只好使用ublock直接永久性制裁了http*://*.*.*/*/*/*/js/enc_js_exam.js这个url(把链接打码了),刷新后就告别debugger了。缺点是万一以后某星把网页加载所必须的代码也放在这里就不能这么玩了。
2、经过探索StackOverflow,我逐渐认识到一个事实:我不能移除任何绑定在元素上的匿名函数事件,比如上面的绑定的paste的匿名事件
3、经过探索StackOverflow,我也试了另一种方法,复制一个dom后把原来的dom节点删除,这样带来的变化就是除了outerHTML和以前一致/基本一致,新增的dom还移除了旧dom绑定的所有event,包括一切子元素的一切event(本来我不希望赶尽杀绝,而是只去除所有的paste事件,结果发现这么做基于火狐浏览器是不现实的)。后来尝试了一下,发现不知道为什么,并不能保存我的答案,因此放弃该计划。
//和该方法根本上是一致的!是一致的变体还有包括但不限于:使用element.parentNode.innerHTML += '';或者使用element.outerHTML=element.outerHTML
4、经过探索StackOverflow,终于找到一个可行的方案,不得不说洋人的StackOverflow就是好啊
document.querySelector('#ueditor_0').contentWindow.addEventListener('paste', function(event) { event.stopImmediatePropagation(); }, true);
//我目前有一点不太明白的是,尽管上面可以给iframe里面的window添加事件监听器,但不代表就不满足cors策略了,倘若我想定位此iframe里的元素还是不行滴,所以我很矛盾啊
ueditor_0是测试页面的iframe的id,而我们需要粘贴内容的框是在这个iframe里的body里,阻止粘贴的paste事件也绑定在这个body上。上面代码的奥妙在于,通过使用addEventListener给window又绑了一个paste事件监听器。众所周知事件是有捕捉和冒泡阶段的,捕捉是从根到叶子的顺序触发事件,冒泡是反着的。可以认为window.document.body是爷爷-父亲-儿子的关系,而addEventListener后面传入的true表示在捕捉阶段执行,也就是同样是paste这个事件,在文本框粘贴时,会先触发window的paste,再触发页面body的paste事件。而我们做的是在触发了window的paste以后就stopImmediatePropagation()了,停止后面的捕捉和冒泡。
其结果就是,终于可以直接在文本框用鼠标右键粘贴了!虽然代价是不能够再使用paste事件的监听了,不过貌似也可以通过自制事件的方法绕开它,我就不细究了
浙公网安备 33010602011771号