将元素绑定到伪事件而不使用 eval

问题描述 投票:0回答:1

我有一个大型旧版 Web 应用程序,需要符合 CSP(内容安全策略)要求。 它充满了内联事件处理程序,例如

onclick =“警报('你好')”

我正在尝试编写一些js,它将在加载时扫描页面并用动态分配的处理程序替换所有这些内联处理程序,例如

var oc = $("#btn").attr("onclick");

$("#btn").on("点击", function(){oc});

这显然行不通,我提前不知道每个内联事件是什么,所以需要将其添加为字符串。 问题是我无法找到符合 CSP 标准的方法。 我尝试用伪事件替换所有真正的内联处理程序,例如 onclick 变成 zclick ,然后提取这些 plsurdo 处理程序并创建真正的动态处理程序:

var oc = $("#btn").attr("zclick"); var func = 函数(oc); btn.on("点击", func);

但 CSP 认为这是“不安全的评估”。 我尝试发现 Angular 是如何做到这一点的,比如它如何将 ng-click 转换为真正的 onclick 事件,但它似乎是极低级别的自定义编译或类似的。 有人对我如何实现这一目标有任何想法吗?

谢谢!

javascript jquery content-security-policy
1个回答
0
投票

既然你说我们不能使用 eval(),我们可以用我们所有的事件监听器创建一个 JS 字符串,并将其动态加载为脚本......

const Events=[
 'abort','afterprint','animationcancel','animationend','animationiteration','animationstart','audioprocess','auxclick','beforeprint','beforeunload','blur','broadcast','canplay','canplaythrough','change',
 'CheckboxStateChange','checking','click','close','complete','compositionend','compositionstart','compositionupdate','contextmenu','copy','cut','dblclick','downloading','drag','dragend','dragenter',
 'dragleave','dragover','dragstart','drop','durationchange','emptied','ended','error','focus','focusin','focusout','fullscreenchange','fullscreenerror','hashchange','input','invalid','keydown',
 'keypress','keyup','load','loadeddata','loadedmetadata','loadend','loadstart','message','mousedown','mouseenter','mouseleave','mousemove','mouseout','mouseover','mouseup','noupdate','obsolete',
 'offline','online','open','pagehide','pageshow','paste','pause','play','playing','pointerlockchange','pointerlockerror','popstate','progress','RadioStateChange','ratechange','readystatechange','reset',
 'resize','scroll','seeked','seeking','select','show','stalled','storage','submit','suspend','timeout','timeupdate','transitioncancel','transitionend','transitionrun','transitionstart','unhandledrejection',
 'unload','updateready','ValueChange','volumechange','waiting','wheel'];


var E=document.querySelectorAll('*'), A='', Z='', S='';


for(let x=0; x<E.length; x++){

 for(let y=0; y<Events.length; y++){

  // In the next line we we need to create an ID if not found, using a random number

  if(E[x].hasAttribute('id')===false){E[x].id='e'+RandomNum(99999);} 

  A='on'+Events[y];

  if(E[x].hasAttribute(A)){

   Z=E[x].getAttribute(A);

   E[x].removeAttribute(A);

   S+=E[x].id.toString()+'.addEventListener(\''+A.slice(2)+'\',function(e){'+Z.replace(/'/g,'"')+'},false);';

}}}


var N=document.createElement('script');

N.type='text/javascript';

// N.onload=function(){alert('Loaded!');}; // We don't actually need this

N.text=S;

document.getElementsByTagName('HEAD')[0].appendChild(N);

备注:

1: 未提供随机数生成功能。

2:整个事情完全是未经测试的代码。

3:一个有趣的挑战,感谢给我锻炼大脑的机会。

© www.soinside.com 2019 - 2024. All rights reserved.