2013-09-05 277 views
26

新しいURLがIEでクロスドメインの場合は、window.openで開いたウィンドウでwindow.openerが利用できないことがわかりました。 How do I detect window opener in IEwindow.openerのクロスドメインセキュリティを回避する方法

これは、ウィンドウが自分のドメインで開始され、それを離してから、自分のドメインに戻った場合に発生します。ポップアップにソーシャルサインアップ(Facebook、Googleなど)をしようとしています。完了すると、新しいウィンドウを閉じてオープナーをリダイレクトする必要があります。

サウンドクラウドがこれを引き離していることは知っていますが、私はどのように考えているのでしょうか。私はFacebookからFacebookへのURLの変更を確認してから閉じる。

サードパーティから戻って自分のサイトにリダイレクトした後、私はこれを実行します。

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

をそれは、ウィンドウが最初にそれからFBにリダイレクト私のドメインは、その後、私に戻ってリダイレクトされたにもかかわらず、IE内で警告。私は自分のサイトを開いてすぐにPHPからリダイレクトすることができると思っていました。しかし、私が自分のサイトを開いたときでさえ、window.location.href = 'facebookssite.com'は戻ってきたときにそれでも苦情を言いました。

NOTE

社会の申し込みはiframe以内にGoogle、FBなどには対応していません。私は彼らがセキュリティの理由からそれらを許可しないと信じています。あなたのiframeから

答えて

25

はそれを他の方法で回避しています。メイン(オープナー)ウィンドウから子ポップアップウィンドウの状態を追跡すると、子ウィンドウがいつあなたのドメインに戻ってナビゲートされたかを簡単に知ることができます。しかし、子ウィンドウを単独で閉じないでください。オープナーウィンドウに子ウィンドウの結果を取得させて閉じます。例えば

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> 

のchild.html:IE10でテスト

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

+1

私はこの考えが好きです。私がオフィスに戻ったときに私はそれを撃つだろう。 –

+0

@Noseratio:あなたのソリューションは、他のドメインのURLがウィンドウで開かれているとうまくいきますが、内部的にFacebookがユーザーを認証し、単にリダイレクトされたURLをウィンドウで開く状況に対処するためにコードを変更するにはどうすればいいですか?その場合、内部リダイレクションが発生しても、leftDomainフラグはfalseです。 –

+0

@ dark_shadow、私はあなたにこれを別の質問として尋ね、これをこの質問にリンクすることをお勧めします。 – Noseratio

1
  1. 、Webページ、ウィンドウは一度行ってどんな
  2. グーグル、ツイッター、に自分自身をリダイレクトyoursite.com
  3. に新しいウィンドウを開くyoursite.com ...上で、OAuthのはリターンをリダイレクトyoursite.com
  4. 新しいウィンドウ上のページへの窓、それはそれを開いたページと同じ起源を持っているため、セキュリティ上の理由から、window.openerにwindow.open
+0

新しいウィンドウは、オープナーとどのように通信しますか? 'window.open( 'mysite.com'、 'parent')'?私は親が実際にそこにいないと思うだろう。または、オープナーがターゲットのIDを持っていることを確認するだけでいいですか?私はすでに1-3をしています –

+0

postmessageを使わないでください。直接のアクセスを使用するだけで、同じオリジンを持つことができます。 'window.opener.globalFuncInOpenerContext()' –

+0

私の質問が更新されました。私のサイトに戻った後、 'window.opener'が本当であることを知ることさえできません。私は何が違うのだろうと思っていて、それはあなたにとって問題ではない。 –

7

を介して通信することができますが削除されたときに赤別のドメインに転送します。戻ってきたら、ブラウザはwindow.openerの復元に気をつけません。あなたの場合、試してみることができます:

1)可能であれば、リダイレクトを使用する代わりに、iframe内で認証を行います。

2)あなたのケースでは、データを親ウィンドウにポストする必要があることがわかります。代わりにこれを試すことができます:

開いたウィンドウでは、dataを保存して通常通り閉じます。

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

window.hasData = true; 
window.data = data; 
window.close(); 

あなたの親ウィンドウがあなたの開いたウィンドウへのアクセス権を有し、その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, ... 
} 

3)回避策:のclosedプロパティを確認するために、あなたの親ページにタイマーを使用しますopenedWindow

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

    } 
},1000); 

4)あなたは、同じドメインにしているようlocalStorageを使用して別の解決策。あなたは親ページでは、あなたのopenedWindowコードイベントに

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

}, true); 

を聞くことができます。

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

if (localStorage){ 
    localStorage.setItem(JSON.stringify(data)); 
} 
window.close(); 
+0

私は私のウィンドウ参照を 'social_window'と名づけました。 'social_window.beforeunload = function(){'決して何も起動しませんでした。 'social_window.onbeforeunload = function(){' FB/Googleへのリダイレクトが発生する前にウィンドウを閉じた場合にのみ起動されます。 –

+0

@Dave Stein:タイマーの使用はどうですか?これはブラウザの振る舞いであるため、このソリューションは素晴らしいソリューションではありません。私たちができることは、回避策を見つけることだけです。 –

+0

@Dave Stein:実行可能な解決策は、可能であればiframe内に認証フォームを読み込むことだと思います。このアプローチでは、ドメインを離れてこの問題を完全に回避する必要はありません。 –

0

私の会社では、異なるドメインを持っており、イントラネットのサイトで公開されているウェブサイトを取得しなければならない場合があります(重複したデータの管理を最終的に取り除くため)。ベン酢に触発さ 私は避けて、このソリューションのシンプルなソリューションに来ている:「getInfo.php

ドメインのWebページへのコール(外部のものと同じ名前を持つ私の場合)

ローカル

<?php 
     $idSp = (isset($_GET['idSp'])?$_GET['idSp']:null); 
     echo file_get_contents('http://192.168.1.10/folder/getInfo.php?idSp='.$idSp); 
?> 

外部 'getInfo.php' リターン

<?php 
    echo '<script>window.opener.manageDisplay('.$getRes.','.$isOK.');</script>'; 
    if($auto_close){ echo "<script>window.close();</script>"; } 
    ?> 
0

localStorageまたはIndexedDBを使用して、同じドメインのドキュメントを表示しているが、相互に参照を持たないウィンドウ間で通信します。

高速タイマーでデータをチェックし、別のデータを保存してレシートを確認し、他のウィンドウでそれを見つけて閉じることができます。

簡潔に言えば、コマンドを渡すためにlocalStorageを使用し、実行したコマンドを削除して戻り値を送信するライブラリを持つことさえできます。