动力节点浅谈JS中的函数劫持


  说到劫持,第一反应可能是什么不好的东西。函数劫持并不邪恶,关键是看使用的人。虽然这个概念在前端领域使用较少,但是在安全领域、自定义业务等场景下还是有一定的使用价值的。所以,动力节点的老师带大家一起去了解一下JS中的函数劫持是什么,有什么用。

 

  基本概念

 

  函数劫持,顾名思义,即在一个函数运行之前把它劫持下来,添加我们想要的功能。当这个函数实际运行的时候,它已经不是原本的函数了,而是带上了被我们添加上去的功能。这也是我们常见的钩子函数的原理之一。

 

  乍一看上去,这很像是函数的改写。函数的改写也可以理解为是函数劫持的一种,但是这种方式太恶心了。作为一个劫持者,在绑票获得好处以后也应该遵守职业道德,把人原封不动地还回去,所以我们得在合适的地方把函数原本的功能给重新调用回来。

 

  推而广之,其实“劫持”这一概念我们经常会遇到,比方说某网站被运营商劫持了,在浏览该网站的时候会弹出运营商的广告。

 

  举例分析

 

  现在我们来举个简单的例子,劫持一下alert()函数,为它增添一点小小的功能:

 

  1.let warn = alert 

 

  2.window.alert = (t) => { 

 

  3.    if (confirm('How are you?')) warn(t) 

 

  4.} 

 

  5. 

 

  6.alert('Help me...!!!')  

 

  可以打开开发者工具尝试一下这个例子,你会发现只有你在confirm里面点击了OK,才会弹出Helpme...!!!。

 

  接下来我们把这部分的内容封装一下,成为一个通用的函数:

 

  1.const hijack = (obj, method, fun) => { 

 

  2.  let orig = obj[method] 

 

  3.  obj[method] = fun(orig) 

 

  4.}  

 

  首先我们定义了一个hijack函数,它会先把原函数给保存下来,然后执行自定义函数,而原函数将会在自定义函数内部进行调用。

 

  然后我们来劫持confirm()函数:

 

  1.hijack(window, 'confirm', (orig) => { 

 

  2.  return (text) => { 

 

  3.    alert('HELP ME PLZ!!!') 

 

  4.    if (orig.call(this, text)) { 

 

  5.      alert('YOU SEEMS FINE AND I AM LEAVING, GOOD BYE!') 

 

  6.    } else { 

 

  7.      alert('HOLD ON! I AM COMING!!') 

 

  8.    } 

 

  9.  } 

 

  10.})  

 

  这段函数的功能很简单就不详细说明了,直接调用confirm()你就知道了。

 

  反劫持

 

  新建一个页面,打开你的开发者工具控制台,输入alert,你会看到这样的输出:

 

  1.function alert() { [native code] } 

 

  然后使用本文开头的那段代码,把alert()劫持一下,再重新在控制台输入alert,你会看到这样的输出:

 

  1.function (t) => { 

 

  2.    if (confirm('How are you?')) warn(t) 

 

  3.}  

 

  通过上述的例子可以知道,要看一个函数是否被劫持了,只需要直接把它打印出来即可。针对系统原生的函数,[nativecode]即代表它是纯净无污染的。

 

  函数劫持的作用

 

  除了为函数增加功能以外,还能够利用函数劫持去追踪恶意用户的信息。一般的XSS攻击会先利用alert()等能够输出信息的方法进行测试,这时候我们可以先对原生alert()进行劫持,向其输入追踪信息的代码,然后才把原函数释放出去。当恶意用户在测试alert()的时候就会立即被我们追踪,而他本人却无从察觉。

 

  后记

 

  关于JS的函数劫持,也不是什么新鲜的东西,只是有同学在最近的工作中遇到了这个知识点感觉比较陌生,过来咨询了一下,动力节点的Java老师花了一些时间总结了一下,如果同学们还有其他见解,可以关注动力节点的官方微信去调戏虎生的小师妹,给动宝儿留言。

 

  

 

上一篇:4个费劲心思却走向编程地狱的陷阱
下一篇:JavaScript的内部字符编码是UCS-2还是UTF-16

开班信息