如何检测跨域iframe中的点击?即防止点击欺诈。

9
我收到了广告系统提供商的欺诈点击警告,但没有更多详细信息。他们建议“为那些快速点击广告的用户隐藏广告”。我编写了一段JS脚本,当用户点击广告时,使用cookie将所有带广告的DIV隐藏N秒钟。但是这个解决方案不起作用,因为“内部”内容(带广告)是由调用并呈现来自外部服务器的内容的JS脚本生成的(正如您从广告系统中期望的那样)。因此,考虑到跨域安全性,这有点像进退两难。我该如何检测一个DIV(本地定义),其内容由外部JS和iframe呈现?

示例:

<div class="ad-class"> <!-- locally defined div -->
   <div id="my-id"> </div> <!-- identifies my ad in the provider's system -->
   <script>
      var foo = blah // declares the ad dimensions and stuff
      //  and renders the contextual ad in #my-id DIV
   </script>
</div>

如果所有内容都是本地的,解决方案就很容易,因为内部div会继承父类(“ad-class”)。但是在跨域的情况下,这种方法不适用。有什么建议吗,伙计们?

你可以始终使用 onclick 事件检测对 div 的点击,而不必关心 div 内部的内容。但是,你可以检查 divinnerHTML 是否已加载广告或为空,如果广告已加载,则运行你的脚本。 - EhsanT
嗨,EhsanT,我希望你是对的,但不幸的是,在这里onclick不起作用。 - olaf
6个回答

12

您无法检测跨域iframe中的点击事件。

话虽如此,您可能有一个不太好的选择:

您可以尝试检测焦点是否从您的窗口移动到了iframe中:

window.focus(); //force focus on the currenct window;
window.addEventListener('blur', function(e){
    if(document.activeElement == document.querySelector('iframe'))
    {
        alert('Focus Left Current Window and Moved to Iframe / Possible click!');
    }
});

http://jsfiddle.net/wk1yv6q3/

然而,它并不可靠,失去焦点并不意味着点击,因为它可能是用户使用 TAB 在网站上移动。

另一个问题是,你只能检测到焦点第一次移动到 iframe 上时的情况,你不知道用户在其中做了什么,他可以点击无数次,而你永远不会知道。


非常感谢,Luizgrs。这是目前为止最好的解决方案。使用TAB浏览网站的人的概率非常低。点击广告文本而不是链接的概率也很低。就像我说的,在点击(或任何交互)之后,广告div会被隐藏,iframe中的此类交互的时间存储在cookie中。如果访问者继续浏览网站,则再次读取cookie,并在N秒后再次显示广告div。 - olaf
但是,我觉得广告提供商的要求有点愚蠢。顺便问一下,我想知道如何保护Adsense广告位免受点击欺诈(我现在没有使用Adsense,但一直在考虑转用它)。 - olaf
这个解决方案在Firefox的最新版本中无法正常工作。有什么方法可以修复它吗? - Vivek Sancheti
谢谢你的启发,也许你会对我的答案感兴趣,它是你的升级版。 - AnonBird

10

Luizgrs 的解决方案启发了我:

var clickIframe = window.setInterval(checkFocus, 100);
var i = 0;

function checkFocus() {
  if(document.activeElement == document.getElementById("ifr")) {
   console.log("clicked "+(i++));
   window.focus();
   }
}
<!DOCTYPE html>
<h2>Onclick event on iframe</h2>
<iframe src="https://www.brokenbrowser.com/" id="ifr"></iframe>

该函数检测 iframe 是否具有焦点,如果是,则用户单击了 iframe。然后我们将焦点返回到主窗口,这样可以找出用户是否再次单击。

对我来说,这个技巧在进行两步式 iframe 点击劫持的 POC 时非常有用。知道用户第一次单击 iframe 的时间使我能够重新组织我的不同层,以保持完美的幻觉。


1
我之前在为动态 iframe 编写类似的脚本,而你提供的 window.focus 就是我所需要的失落的一块拼图!谢谢你。 - eleytheria

1

@Luizgrs指出的方法非常准确,但是我成功地使用了该方法的变体来检测点击事件:

var iframeMouseOver = false;
    $("YOUR_CONTAINER_ID")
        .off("mouseover.iframe").on("mouseover.iframe", function() {
            iframeMouseOver = true;
        })
        .off("mouseout.iframe").on("mouseout.iframe", function() {
            iframeMouseOver = false;
        });

    $(window).off("blur.iframe").on("blur.iframe", function() {
        if(iframeMouseOver){
            $j("#os_top").click();
        }
    });

上面的代码在桌面端运行得非常好,如果你想添加移动支持,你只需要使用触摸事件touchstarttouchend事件来模拟移动设备上的mouseover。

源代码


或者对于支持指针事件的浏览器,使用指针事件而不是鼠标/触摸。 - Zach Saucier

0

插件首先搜索任何由先前指定的类名包装的iframe。

iframe id将被收集到一个数组中,对于这些id中的每一个,都将创建一个mouseover事件,触发隐藏类'cfmonitor'的脚本。结果是包含广告的iframe不再可见。

// IFRAME ACTION
    function iframeAction () {
        jq.each(jq.cfmonitor.iframes, function(index,element) {
            frameID = jq(element).attr('id') || false;
            if (frameID) initiateIframe(frameID);
            //alert (frameID);
        });
    }

    // INIT IFRAME
    function initiateIframe(elementID) {
        var element = document.getElementById(elementID);
        // MOUSE IN && OUT
        if (element) {
            element.onmouseover = processMouseOver;
            element.onmouseout = processMouseOut;
            //console.log("mouse on out");
        }
        // CLICKS
        if (typeof window.attachEvent !== 'undefined') {
            top.attachEvent('onblur', processIFrameClick);
        }
        else if (typeof window.addEventListener !== 'undefined') {
            top.addEventListener('blur', processIFrameClick, false);
        }
}

// IFRAME CLICKS
    function processIFrameClick() {
        // ADD A CLICK
        if(isOverIFrame) {
            //addClick();
            // Some logic here to hide the class 'cfmonitor'
            //console.log("Go");
            top.focus();
        }
}

0

前段时间我发现了WordPress的这个插件。很明显它可以满足我的需求-只是想知道这家伙是如何让它起作用的,它可以统计Adsense iframe上的点击次数。虽然我不是PHP程序员,但我必须仔细研究一下。我主要使用Python编程,并需要Django的这种解决方案。如果有人能轻松阅读代码,我将非常感激任何帮助。


0

看看这个,可能会有帮助。当它跨浏览器时,您无法检测到点击事件。

window.focus();
window.addEventListener('blur', function(e){
  if(document.activeElement == document.getElementById('Your iframe id'))
   {
    console.log('iframe click!');
   }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接