0

使用 JavaScript,我想在文档中的每个内联事件处理程序被触发之前拦截它们的注册。对于文档的静态节点(即不是由脚本动态注入的节点),我想移除内联事件处理程序并将它们转换为外部事件处理程序(外部处理程序意味着直接node.AddEventListener从 JavaScript 调用函数)。然而,对于动态节点,我想保留内联事件处理程序(动态节点是使用 JavaScript 注入的节点)。

例如:

<body>
<img onerror="alert(1)" />
<script>
document.getElementById("a").innerHTML = "<img onerror='alert(2)'/>";
</script>
<div id="a"></div>
</body>

在上面的示例中,我希望将 alert(1) 错误事件转换为外部事件,同时将 alert(2) 错误事件保持在内联。我知道如何将内联事件处理程序转换为外部事件处理程序,但我不知道如何 1)在“注册”时和实际触发之前拦截内联处理程序。2)区分静态节点和动态节点的处理程序。

我知道这是一个难题,但任何帮助/评论都会很棒:)

4

2 回答 2

0

在触发或注册其他内联事件处理程序之前,您可以观察两个有用的 DOM 事件。您应该注意window.onloadDOMContentLoaded事件。

onload当所有页面内容包括所有资源(CSS、JS、图像等)时触发 该事件。DOMContentLoaded另一方面,当文档完成加载(DOM 已准备好)而不是其依赖资源时触发。意味着 HTML 标记、文本和样式已准备就绪。

为此,jQuery 有一个跨浏览器的.ready()事件。

$(document).ready(function() {
    // do something when the DOM is ready.
});

您可以在活动开始前打断onerror。如果您想通过 javascript(和 jQuery)轻松使用元素,则应该为元素分配 ID 或类:<img id="img1" onerror="alert(1)" />. 因此,假设您想摆脱onerror事件触发的警报;例如,您可以这样做:

$(document).ready(function() {
    $('#img1').unbind('error');
    //OR $('img').first().unbind('error'); 
            //to get the first image element from your actual code
});

这将删除(未绑定)元素error上的事件处理程序。img1如果要从所有图像中删除错误事件处理程序,可以这样做:

$('img').unbind('error');

如果要删除旧的并将新的错误事件分配给特定元素:

$('#img1').unbind('error').error(function(event){
    // do stuff...
});

回答你的第二个问题;您无法真正区分静态和动态添加的事件处理程序。但是,您只需将代码放在添加动态处理程序的行之前。

希望这可以帮助。

于 2013-01-16T13:12:30.143 回答
0

我不知道如何拦截内联事件的注册,但是可以拦截内联脚本的执行

虽然浏览器不提供控制内联事件的接口,但内联事件也是遵守 W3C 规范的 DOM 事件。要了解以下实现,最好了解 HTML DOM API 中的事件传播知识:冒泡和捕获,事件传播的两种方式

根据上面的文章,在所有浏览器中(除了IE<9),事件处理都有两个阶段。事件首先下降 - 这称为捕获,然后冒泡。这种行为在 W3C 规范中是标准化的。因此,我们可以通过将事件绑定到父节点来在捕获阶段拦截节点的内联事件。例如:

<img src="" onerror="alert('Yahoo!');" id="target" />
<script>
    document.addEventListener('error', function(e) {
        var element = e.target;
        if (element.id == "target") {
            e.stopImmediatePropagation();
            console.log("The alert is intercepted.");
        }
    }, true);
</script>

我们在上面绑定到文档的事件将在 img.onerror 之前执行,并e.stopImmediatePropagation()阻止当前事件的进一步传播。因此,没有机会触发内联 onerror 事件。

参考: http: //fex.baidu.com/blog/2014/06/xss-frontend-firewall-1/

于 2015-01-29T16:00:57.557 回答