2013-09-05 17 views
26

Tôi vừa phát hiện ra rằng window.opener không có sẵn trong cửa sổ được mở qua window.open nếu URL mới là tên miền chéo, trong IE. How do I detect window opener in IELàm cách nào để nhận được bảo mật giữa các cửa sổ.opener

Điều này sẽ xảy ra nếu cửa sổ bắt đầu trong miền của tôi, thoát khỏi đó và sau đó quay lại miền của tôi. Tôi đang cố gắng để có một đăng ký xã hội (facebook, google, vv) trong cửa sổ bật lên. Khi nó hoàn thành nó sẽ đóng cửa sổ mới và chuyển hướng mở.

Tôi biết rằng Soundcloud đang tắt chức năng này, nhưng tôi không biết làm cách nào. Tôi thấy sự thay đổi URL từ họ đến Facebook, và sau đó đóng lại.

Sau khi chuyển hướng trở lại trang web của tôi từ bên thứ 3 tôi chạy này:

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

Nó cảnh báo trong IE, mặc dù cửa sổ ban đầu là tên miền của tôi, sau đó chuyển hướng đến FB, sau đó chuyển hướng trở lại với tôi . Tôi nghĩ có thể kể từ khi tôi mở trang web của tôi và chuyển hướng ngay lập tức từ PHP có thể là một vấn đề. Tuy nhiên ngay cả khi tôi mở trang web của mình, đã làm window.location.href = 'facebookssite.com' nó vẫn bị khiếu nại khi trở về.

LƯU Ý

đăng ký xã hội không làm việc cho google, FB, vv trong một iframe. Tôi tin rằng họ không cho phép họ vì lý do an ninh.

Trả lời

25

Do nó là cách khác xung quanh. Theo dõi trạng thái của cửa sổ bật lên con từ cửa sổ chính (mở), và bạn có thể dễ dàng biết khi nào cửa sổ con được điều hướng trở lại miền của bạn, vì vậy bạn có thể "nói chuyện" lại với nó. Nhưng không tự đóng cửa sổ con. Hãy để cửa sổ mở có được kết quả từ cửa sổ con và sau đó đóng nó lại.

Ví dụ, 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> 

Thử nghiệm với IE10.

+1

Tôi thích ý tưởng này. Tôi sẽ quay lại khi tôi quay lại văn phòng. –

+0

@Noseratio: Giải pháp của bạn hoạt động tốt nếu url của miền khác được mở trong cửa sổ nhưng làm cách nào chúng tôi có thể sửa đổi mã của bạn để xử lý tình huống trong đó Facebook xác thực người dùng và chỉ cần mở url được chuyển hướng trong cửa sổ. Trong trường hợp đó leftDomain flag là false, mặc dù có một số chuyển hướng nội bộ đã xảy ra. –

+0

@dark_shadow, tôi khuyên bạn nên đặt câu hỏi này như một câu hỏi riêng và liên kết câu hỏi này với câu hỏi đó. – Noseratio

1
  1. Từ iframe của bạn, trang web, trên yoursite.com ... mở một cửa sổ mới trên yoursite.com
  2. Cửa sổ chuyển hướng riêng của mình cho Google, Twitter, bất cứ điều gì
  3. Khi đã xong, các OAuth chuyển hướng lợi nhuận cửa sổ đến một trang trên
  4. cửa sổ mới yoursite.com, bởi vì nó có nguồn gốc tương tự như các trang đó mở nó ra, có thể giao tiếp qua window.open
+0

Cửa sổ mới, giao tiếp với công cụ mở của nó như thế nào? 'window.open ('mysite.com', 'parent')'? Tôi nghĩ cha mẹ sẽ không thực sự ở đó. Hoặc tôi chỉ cần đảm bảo rằng trình mở có ID cho mục tiêu. Tôi đã làm 1-3 –

+0

Không sử dụng postmessage. Chỉ cần sử dụng truy cập trực tiếp, bạn có thể làm vì chúng có cùng nguồn gốc. 'window.opener.globalFuncInOpenerContext()'. –

+0

Tôi đã cập nhật câu hỏi của mình. Nó thậm chí không biết 'window.opener' là có thật sau khi trở về trang web của tôi. Tôi tự hỏi những gì có thể khác nhau mà nó hoạt động không có vấn đề cho bạn. –

7

vì lý do an ninh, window.opener được lấy ra khi đỏ irecting đến một tên miền khác nhau. Trình duyệt không bận tâm khôi phục window.opener khi bạn quay lại. Trong trường hợp của bạn, bạn có thể thử:

1) Xác thực của bạn trong iframe nếu có thể thay vì sử dụng chuyển hướng.

2) Trong trường hợp của bạn, tôi thấy rằng bạn cần đăng dữ liệu trở lại cửa sổ chính. Bạn có thể thử thay vào đó:

Trong cửa sổ đã mở, chỉ cần lưu data và đóng bình thường.

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

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

cửa sổ cha mẹ của bạn có quyền truy cập vào cửa sổ mở của bạn và có thể xử lý close sự kiện của nó:

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) Một cách giải quyết: Sử dụng một bộ đếm thời gian trong trang cha mẹ của bạn để kiểm tra sự closed tài sản của openedWindow

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

    } 
},1000); 

4) Một giải pháp khác sử dụng localStorage khi bạn ở trên cùng một miền.Bạn trang mẹ có thể nghe sự kiện

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

}, true); 

đang openedWindow của bạn:

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

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

Tôi đặt tên tham chiếu cửa sổ là 'social_window'. 'social_window.beforeunload = function() {' không bao giờ bắn bất cứ thứ gì. 'social_window.onbeforeunload = function() {' chỉ được kích hoạt nếu tôi đóng cửa sổ trước khi chuyển hướng đến FB/Google của tôi đã xảy ra. –

+0

@Dave Stein: làm thế nào về việc sử dụng một bộ đếm thời gian? Giải pháp này không tốt vì chúng tôi không thể có giải pháp tốt vì đây là hành vi của trình duyệt. Tất cả những gì chúng ta có thể làm là cố gắng tìm cách giải quyết. –

+0

@Dave Stein: Tôi nghĩ rằng giải pháp khả thi là tải biểu mẫu xác thực bên trong iframe nếu có thể. Với cách tiếp cận này, chúng tôi không phải rời khỏi miền của mình và tránh hoàn toàn vấn đề này. –

0

Trong công ty của tôi, chúng tôi có các miền khác nhau và có trường hợp trang web của mạng nội bộ phải có trang web công cộng của chúng tôi (để cuối cùng thoát khỏi việc duy trì dữ liệu trùng lặp). Lấy cảm hứng ở Bến Giấm tôi đã đến giải pháp này đơn giản giải pháp tránh:

Gọi vào trang web tên miền (trong trường hợp của tôi với tên giống như một bên ngoài)

địa phương 'getInfo.php'

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

ngoài 'getInfo.php' trở lại

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

Sử dụng localStorage hoặc IndexedDB để liên lạc giữa các cửa sổ đang hiển thị tài liệu từ cùng một tên miền nhưng không có tham chiếu đến nhau.

Chỉ cần có bộ đếm thời gian tốc độ cao để kiểm tra dữ liệu, lưu một phần dữ liệu khác để xác nhận việc nhận và cửa sổ kia có thể tìm và đóng.

Tóm lại - bạn sử dụng localStorage để chuyển các lệnh và thậm chí có thể có thư viện để thực hiện việc này và xóa các lệnh khi chúng được thực thi và đăng các giá trị trả về.

Các vấn đề liên quan