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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29337304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 10:24:13  来源:igfitidea点击:

How to detect a click inside of an iframe (cross-domain)? Aka prevent click fraud

javascriptjqueryhtmliframeads

提问by olaf

I got a warning by my ad system provider about click fraud. No further info, all they are recommending is "hide the ads for users who click on ads too quickly'". I wrote a piece of JS script that hides all DIVs with ads for N seconds (using cookie) when clicked on, but this solution does not work as the "inner" content (with ads) is generated by an JS script that calls and renders the content from external server (as you would expect from an ad system). So, when one takes the cross-domain security into account it is kinda Catch 22. How can I detect a click inside a DIV (locally defined) of which content is rendered by an external JS and in iframe?

我的广告系统提供商向我发出了关于点击欺诈的警告。没有更多信息,他们所推荐的只是“为点击广告太快的用户隐藏广告”。我写了一段 JS 脚本,在点击时隐藏所有带有广告的 DIV(使用 cookie)N 秒,但是这个解决方案不起作用,因为“内部”内容(带有广告)是由调用和呈现的 JS 脚本生成的来自外部服务器的内容(正如您对广告系统所期望的那样)。因此,当考虑跨域安全性时,它有点像 Catch 22。如何检测 DIV(本地定义)内的点击,其中的内容由外部 JS 呈现并在 iframe 中呈现?

Example:

例子:

<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>

Were it all local, solution would be easy as the internal div would inherit the parent class ("ad-class"). In case of cross-domain, this is not valid. Any tips, dudes?

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

回答by Luizgrs

You cannot detect click events in cross-domain iframe.

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

That put, you might have one bad option:

也就是说,您可能有一个糟糕的选择:

One of the nearest things you can do is detect that the focus moved from your window to the 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/

http://jsfiddle.net/wk1yv6q3/

However it's not reliable, loose focus does not mean a click, it could be user moving across the website using TAB.

但是它不可靠,松散的焦点并不意味着点击,它可能是用户使用TAB.

Another problem is that, you only detect the first time focus is moved to the iframe, you do not know what user does in there, he can click a million times and you will never know.

另一个问题是,你只检测到第一次焦点移到 iframe 上,你不知道用户在那里做了什么,他可以点击一百万次,你永远不会知道。

回答by AnonBird

Luizgrsinspired me this solution :

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>

The function detect if the iframe has the focus, if yes, the user clicked into the iframe. We then give back the focus to our main windows, which allow us to find if the user click another time.

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

This trick has been usefull to me for a POC on a 2 step iframe click-Hymaning. Getting to know when the user clicked for the first time on the iframe allowed me to reorganize my different layers to keep the illusion perfect.

这个技巧对我在两步 iframe 点击劫持上的 POC 很有用。了解用户第一次在 iframe 上单击的时间使我能够重新组织不同的图层以保持完美的错觉。

回答by Shagun1390

Check this it might help. You can not detect the click event when its cross browser.

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

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

回答by svelandiag

The approach @Luizgrs pointed out is very accurate, however I managed to indeed detect the click event using a variation of the method:

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

The above code works like a charm on desktop if you want to add mobile support you just need to use touch eventstouchstartand touchendevents to simulate the mouseover on mobile.

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

Source

来源

回答by olaf

Well, a while ago I found this plugin for WordPress. Obviously it does what I need -- just wondering how this guy made it to work, it does count clicks on Adsense iframe. I must have a closer look though I am not a PHP programmer. I program mainly in Python and need some solution of this kind for Django. If anyone can read the code easily, I would appreciate any help.

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

回答by Rene Hermenau

The plugin is searching first for any iframe wrapped by a previous specified class name.

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

The iframe id′s will be collected in a array and for everyone of these id′s an mouseover event will be created which fires the script which hides the class 'cfmonitor'. As a result the iframe containing ad is not visible anymore.

iframe id 将被收集在一个数组中,对于这些 id 中的每个人,将创建一个鼠标悬停事件,该事件触发隐藏类“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();
        }
}