如何检测 iframe 内的点击(跨域)?又名防止点击欺诈

Posted

技术标签:

【中文标题】如何检测 iframe 内的点击(跨域)?又名防止点击欺诈【英文标题】:How to detect a click inside of an iframe (cross-domain)? Aka prevent click fraud 【发布时间】:2015-06-02 22:37:38 【问题描述】:

我的广告系统提供商向我发出了关于点击欺诈的警告。没有更多信息,他们只推荐“为点击广告太快的用户隐藏广告”。我写了一段 JS 脚本,在点击时将所有带有广告的 DIV 隐藏 N 秒(使用 cookie),但是这个解决方案不起作用,因为“内部”内容(带有广告)是由调用和呈现的 JS 脚本生成的来自外部服务器的内容(正如您对广告系统所期望的那样)。因此,当考虑到跨域安全性时,它有点像 Catch 22。如何检测 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 中的内容。但您可以检查 div innerhtml 是否已加载广告或广告是否为空,以及广告是否已加载然后运行您的脚本。 嗨,EhsanT,我希望你是对的,但不幸的是,onclick 在这里不起作用。 Detect Click into Iframe using javascript的可能重复 【参考方案1】:

您无法检测跨域 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。 但是,是的,我发现广告提供商的要求有点愚蠢。顺便说一句,我想知道如何保护 Adsense div 免受点击欺诈(我现在没有使用 Adsense,但一直在考虑改用它。) 此解决方案不适用于 Firefox 的最新版本。有什么办法解决吗? 感谢您的启发,您可能有兴趣查看我的回答,这是对您的升级。【参考方案2】:

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 的时间让我能够重新组织不同的图层以保持完美的错觉。

【讨论】:

我对动态 iframe 使用了类似的脚本,而您的 window.focus 是我需要的缺失部分!谢谢你。【参考方案3】:

@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();
        
    );

上面的代码在桌面上就像一个魅力,如果你想添加移动支持,你只需要使用touch eventstouchstarttouchendevents来模拟移动设备上的鼠标悬停。

Source

【讨论】:

对于支持它的浏览器,或者使用指针事件代替鼠标/触摸。【参考方案4】:

好吧,不久前我找到了this plugin for WordPress。显然它可以满足我的需要——只是想知道这个人是如何让它工作的,它确实计算了 Adsense iframe 的点击次数。虽然我不是 php 程序员,但我必须仔细看看。我主要用 Python 编程,需要一些针对 Django 的此类解决方案。如果有人可以轻松阅读代码,我将不胜感激。

【讨论】:

【参考方案5】:

插件首先搜索由先前指定的类名包装的任何 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();
        

【讨论】:

【参考方案6】:

检查它可能会有所帮助。跨浏览器时无法检测到点击事件。

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

【讨论】:

以上是关于如何检测 iframe 内的点击(跨域)?又名防止点击欺诈的主要内容,如果未能解决你的问题,请参考以下文章

如何跨域更改 iframe 内容的样式?

Nginx使用X-Frame-Options防止被iframe跨域

iframe 内的 onload 事件仅触发一次

检测此页面是不是在跨域 iframe 内部的万无一失的方法

在 iframe 跨域中捕获点击位置

跨域post 及 使用token防止csrf 攻击