Подтвердить что ты не робот

Как обойти защиту междоменной безопасности window.opener

Я только узнал, что window.opener недоступен в окне, открывшемся через window.open, если новый URL-адрес является междоменным, в IE. Как обнаружить открыватель окна в 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" );
}

Он оповещает об этом в IE, хотя изначально был мой домен, который затем перенаправлялся в FB, а затем перенаправлялся ко мне. Я думал, может, так как я открываю свой сайт и сразу перенаправляюсь с PHP, что может быть проблемой. Однако даже когда я открыл свой сайт, window.location.href = 'facebookssite.com' он все еще жаловался при возврате.

Примечание

Социальные регистрации не работают для google, FB и т.д. внутри iframe. Я считаю, что они запрещают их по соображениям безопасности.

4b9b3361

Ответ 1

Сделайте это наоборот. Отслеживание состояния всплывающего окна ребенка из главного окна (открывателя), и вы можете легко узнать, когда дочернее окно было перенесено обратно в ваш домен, чтобы вы могли "поговорить" с ним снова. Но не закрывайте дочернее окно самостоятельно. Пусть открывающее окно получит результат из дочернего окна и закроет его.

Например, 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

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

Протестировано с помощью IE10.

Ответ 2

Из-за соображений безопасности window.opener удаляется при перенаправлении в другой домен. Браузер не потрудит восстановить 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, поскольку вы находитесь в том же домене. Ваша родительская страница может прослушивать событие

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

}, true);

Ваш открытый код:

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

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

Ответ 3

  • Из вашего iframe, веб-страницы, на вашем сайте... открывайте новое окно на вашем сайте.
  • Окно перенаправляет себя на Google, Twitter, независимо от того, что
  • После этого перенаправление OAuth возвращает окно на страницу на вашем сайте.
  • Новое окно, так как оно имеет то же происхождение, что и открывшая его страница, может связываться через window.open

Ответ 4

В моей компании у нас разные домены, и там, где сайт интрасети должен получить наш общедоступный веб-сайт (чтобы, наконец, избавиться от обслуживания дублированных данных). Вдохновленный в Ben Vinegar, я пришел к этому решению простым решением, избегая:

Позвоните на веб-страницу домена (в моем случае с тем же именем, что и внешний)

local ' getInfo.php'

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

Внешний ' getInfo.php' return

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

Ответ 5

Используйте localStorage или IndexedDB для связи между окнами, которые показывают документы из того же домена, но которые не имеют ссылки друг на друга.

Просто проверьте высокоскоростной таймер для данных, сохранив еще одну часть данных, чтобы подтвердить получение, а другое окно может найти ее и закрыть.

Короче говоря, вы используете localStorage для передачи команд и можете даже иметь библиотеку для этого и удалять команды после их выполнения и отправлять возвращаемые значения.