Как мне обойти междоменную безопасность 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
, Я считаю, что они запрещают их по соображениям безопасности.
5 ответов
Сделай это наоборот. Отслеживайте состояние дочернего всплывающего окна в главном (открывающем) окне, и вы можете легко узнать, когда дочернее окно было перемещено обратно к вашему домену, чтобы вы могли "поговорить" с ним снова. Но не закрывайте дочернее окно само по себе. Позвольте открывающему окну получить результат из дочернего окна, а затем закройте его.
Например, 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.
По соображениям безопасности, 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();
- Из вашего iframe, веб-страницы на yoursite.com... откройте новое окно на yoursite.com
- Окно перенаправляется в Google, Twitter, что угодно
- После этого перенаправление OAuth возвращает окно на страницу на вашем сайте.
- Новое окно, поскольку оно имеет тот же источник, что и открывшая его страница, может взаимодействовать через window.open.
Используйте localStorage или IndexedDB для связи между окнами, в которых отображаются документы из одного домена, но которые не имеют ссылок друг на друга.
Просто используйте высокоскоростной таймер, проверяющий данные, сохраняя другой фрагмент данных для подтверждения получения, и другое окно может найти его и закрыть.
Короче говоря - вы используете localStorage для передачи команд и даже можете иметь библиотеку для этого, удалять команды после их выполнения и отправлять возвращаемые значения.
Вы можете использовать
window.postMessage()
, который предусмотрен именно для этого сценария.
Пояснение: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
В моей компании у нас разные домены, и есть случай, когда сайт интрасети должен получить наш общедоступный веб-сайт (чтобы, наконец, избавиться от обслуживания дублированных данных). Вдохновленный в Ben Vinegar, я пришел к этому решению, простому решению, избегая:
Звоните на веб-страницу домена (в моем случае с тем же именем, что и внешнее)
местный '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
<?php
echo '<script>window.opener.manageDisplay('.$getRes.','.$isOK.');</script>';
if($auto_close){ echo "<script>window.close();</script>"; }
?>