如何绕过window.opener跨域安全性

Dav*_*ein 37 javascript cross-domain

我刚刚发现,如果新的URL是跨域的,在IE浏览器中window.opener打开的窗口中不可用window.open.如何检测IE中的窗口开启工具

如果窗口在我的域中启动,离开它,然后返回到我的域,则会发生这种情况.我试图在弹出窗口中进行社交注册(facebook,google等).完成后应该关闭新窗口并重定向开启器.

我知道Soundcloud正在关闭它,但我不知道如何.我看到URL从他们改为Facebook,然后关闭.

从第三方重定向回我的网站后,我运行:

var data = {
  type : 'complete',
  destination : '<?= $destination; ?>'
};
if ( window.opener ) {
  window.opener.postMessage( JSON.stringify( data ), '*' );
  window.close();
}
else {
  alert( "Unable to find window" );
}
Run Code Online (Sandbox Code Playgroud)

它在IE中提醒,即使窗口最初是我的域,然后重定向到FB,然后重定向回到我.我想可能因为我打开我的网站并立即从PHP重定向可能是一个问题.然而,即使我打开我的网站,window.location.href = 'facebookssite.com'它仍然在返回时抱怨.

注意

社交注册不适用于谷歌,FB等iframe.我相信他们出于安全原因不允许他们.

nos*_*tio 38

反过来做.从主(开启者)窗口跟踪子弹出窗口的状态,您可以很容易地知道子窗口何时被导航回您的域,因此您可以再次与其"对话".但是不要单独关闭子窗口.让开启窗口从子窗口获取结果然后关闭它.

例如,main.html:

<!DOCTYPE html>
<head>
<title>main</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<script>
window.addEventListener("message", function(ev) {
    if (ev.data.message === "deliverResult") {
        alert("result: " + ev.data.result);
        ev.source.close();
    }
});

function Go() {
    var child = window.open("child.html", "_blank", "height=200,width=200");

    var leftDomain = false;
    var interval = setInterval(function() {
        try {
            if (child.document.domain === document.domain)
            {
                if (leftDomain && child.document.readyState === "complete")
                {
                    // we're here when the child window returned to our domain
                    clearInterval(interval);
                    alert("returned: " + child.document.URL);
                    child.postMessage({ message: "requestResult" }, "*");
                }
            }
            else {
                // this code should never be reached, 
                // as the x-site security check throws
                // but just in case
                leftDomain = true;
            }
        }
        catch(e) {
            // we're here when the child window has been navigated away or closed
            if (child.closed) {
                clearInterval(interval);
                alert("closed");
                return; 
            }
            // navigated to another domain  
            leftDomain = true;
        }
    }, 500);
}
</script>
</head>
<body>
<button onclick="Go()">Go</button>
</body>
Run Code Online (Sandbox Code Playgroud)

child.html:

<!DOCTYPE html>
<head>
<title>child</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<script>
window.addEventListener("message", function(ev) {
    if (ev.data.message === "requestResult") {
        // ev.source is the opener
        ev.source.postMessage({ message: "deliverResult", result: true }, "*");
    }   
});
</script>
</head>
<body>
<a href="http://www.example.com">Go to example.com</a>
Then click the browser Back button when ready.
</body>
Run Code Online (Sandbox Code Playgroud)

用IE10测试.


Kha*_* TO 14

由于安全原因,window.opener在重定向到其他域时会被删除.window.opener当您回来时,浏览器无需恢复.在您的情况下,您可以尝试:

1)如果可能,请在iframe中进行身份验证,而不是使用重定向.

2)在您的情况下,我发现您需要将数据发布回父窗口.你可以试试这个:

在打开的窗口中,只需存储data并正常关闭即可.

var data = {
  type : 'complete',
  destination : '<?= $destination; ?>'
};

window.hasData = true;
window.data = data;
window.close();
Run Code Online (Sandbox Code Playgroud)

您的父窗口可以访问您打开的窗口并可以处理其close事件:

openedWindow.beforeunload = function (){
    //here you could access this.data or openedWindow.data because you're on the same domain
    if (this.hasData){
    }
    //Reason we have this check is because the beforeunload event fires whenever the user leaves your page for any reason including close, submit, clicking a link, ...
}
Run Code Online (Sandbox Code Playgroud)

3)解决方法:在父页面中使用计时器来检查closed属性openedWindow

setInterval(function(){
   if (openedWindow.closed){

   }
},1000);
Run Code Online (Sandbox Code Playgroud)

4)使用localStorage的另一种解决方案,因为您在同一个域中.您的父页面可以收听该事件

window.addEventListener("storage", function(event){

}, true);
Run Code Online (Sandbox Code Playgroud)

你的opensWindow代码:

var data = {
  type : 'complete',
  destination : '<?= $destination; ?>'
};

if (localStorage){
   localStorage.setItem(JSON.stringify(data));
}
window.close();
Run Code Online (Sandbox Code Playgroud)