Làm cách nào để xác định xem một trang web đang được tải bên trong iframe hay trực tiếp vào cửa sổ trình duyệt?


597

Tôi đang viết một iframe dựa trên ứng dụng facebook. Bây giờ tôi muốn sử dụng cùng một trang html để hiển thị trang web bình thường cũng như trang canvas trong facebook. Tôi muốn biết liệu tôi có thể xác định xem trang đã được tải bên trong iframe hay trực tiếp trong trình duyệt không?


2
Một vài cách hay (bao gồm cả nhận xét): tommcfarlin.com/check-if-a-page-is-in-an-iframe
simhumileco

Câu trả lời:


1108

Trình duyệt có thể chặn quyền truy cập window.topdo chính sách xuất xứ tương tự . Lỗi IE cũng diễn ra. Đây là mã làm việc:

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

topselflà cả hai windowđối tượng (cùng với parent), vì vậy bạn sẽ thấy nếu cửa sổ của bạn là cửa sổ trên cùng.


4
Điều này dường như hoạt động tốt trong Firefox. Nó cũng hoạt động trong các trình duyệt khác?
akshat

5
Có một trang có iframe trong iframe, để kiểm tra iframe của con tôi nếu iframe của bố mẹ tôi được nhúng vào trang, tôi đã sử dụng if (
Parent

7
@sglessard Nếu trang con và cha mẹ đến từ các miền khác nhau thì Firefox sẽ khiếu nại Chính sách nguồn gốc giống nhau (www.w3.org/Security/wiki/Same_Origin_Policy) và mã sẽ không hoạt động
Gaurang Jadia

18
Điều này hoạt động trong IE 11, 10 và 9 đối với tôi. Ngoài ra, nó hoạt động trong FF và Opera, tất nhiên, Chrome. Tôi không gặp phải bất kỳ vấn đề nào với nó.
jeremysawgie

4
Đối với những người vẫn khuấy động công nghệ mới nhất vào năm 1995, window.self !== window.topsẽ trả về truekhi chạy từ trong nội dung của frame, hoặc iframe .
Jeromy Pháp

84

Khi trong iframe có cùng nguồn gốc với cha, window.frameElementphương thức trả về phần tử (ví dụ iframehoặc object) trong đó cửa sổ được nhúng. Mặt khác, nếu duyệt trong ngữ cảnh cấp cao nhất hoặc nếu khung cha và khung con có nguồn gốc khác nhau, nó sẽ đánh giá null.

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'

Đây là một Tiêu chuẩn HTML với sự hỗ trợ cơ bản trong tất cả các trình duyệt hiện đại.


2
Lưu ý khi cố đọc frameElementsẽ ném ngoại lệ SecurityError trong các iframe gốc, theo W3C ( WHATWG nói rằng nó sẽ trả về null thay thế). Vì vậy, bạn có thể muốn bọc nó trong một try...catchtuyên bố.
Oriol

5
nhận được nullbên trong và bên ngoàiiframe
OlehZiniak

4
Mô tả tại MDN nói rằng "nếu tài liệu được nhúng vào nó có nguồn gốc khác nhau (chẳng hạn như được đặt từ một tên miền khác), thì đây là null."
xeophin

Chỉ để xác nhận sự trở lại nên là:Returns the element (such as <iframe> or <object>) in which the window is embedded, or null if the element is either top-level or is embedded into a document with a different script origin; that is, in cross-origin situations.
Art3mix 7/12/18

26

RoBorg là chính xác, nhưng tôi muốn thêm một ghi chú bên.

Trong IE7 / IE8 khi Microsoft thêm Tab vào trình duyệt của họ, họ đã phá vỡ một điều sẽ gây ra sự tàn phá với JS của bạn nếu bạn không cẩn thận.

Hãy tưởng tượng bố cục trang này:

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")

Bây giờ trong khung "baz", bạn nhấp vào một liên kết (không có mục tiêu, tải trong khung "baz") nó hoạt động tốt.

Nếu trang được tải, hãy gọi nó là Special.html, sử dụng JS để kiểm tra xem "nó" có khung cha có tên là "bar" hay không, nó sẽ trả về đúng (dự kiến).

Bây giờ hãy nói rằng trang Special.html khi tải, kiểm tra khung chính (để biết sự tồn tại và tên của nó và nếu là "thanh", nó sẽ tự tải lại trong khung thanh. Ví dụ:

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}

Càng xa càng tốt. Bây giờ đến lỗi.

Hãy nói thay vì nhấp vào liên kết ban đầu như bình thường và tải trang Special.html trong khung "baz", bạn nhấp vào giữa hoặc chọn mở trong Tab mới.

Khi tab mới đó tải (hoàn toàn không có khung chính! ) IE sẽ nhập một vòng vô tận tải trang! bởi vì IE "sao chép" cấu trúc khung trong JavaScript sao cho tab mới DOES có cha mẹ và cha mẹ đó có tên "thanh".

Tin tốt là kiểm tra:

if(self == top){
  //this returns true!
}

trong tab mới đó trả về true và do đó bạn có thể kiểm tra điều kiện kỳ ​​lạ này.


Đã sửa lỗi trong thời gian này? Tôi không thể sao chép nó trong IE8. Tôi luôn luôn nhận được chính xác window.parent.
dùng123444555621

1
Không chắc chắn - Tôi sẽ chạy bộ thử nghiệm của mình với IE9 trở xuống và đăng cập nhật.
scunliffe

18

Câu trả lời được chấp nhận không hoạt động đối với tôi bên trong tập lệnh nội dung của Tiện ích mở rộng Firefox 6.0 (Addon-SDK 1.0): Firefox thực thi tập lệnh nội dung trong mỗi: cửa sổ cấp cao nhất và trong tất cả các iframe.

Bên trong tập lệnh nội dung tôi nhận được các kết quả sau:

 (window !== window.top) : false 
 (window.self !== window.top) : true

Điều kỳ lạ về đầu ra này là nó luôn giống nhau bất kể mã được chạy bên trong iframe hay cửa sổ cấp cao nhất.

Mặt khác, Google Chrome dường như chỉ thực thi tập lệnh nội dung của tôi một lần trong cửa sổ cấp cao nhất, do đó, phần trên không hoạt động.

Điều cuối cùng đã làm cho tôi trong một kịch bản nội dung trong cả hai trình duyệt là:

 console.log(window.frames.length + ':' + parent.frames.length);

Không có iframe này in 0:0, trong một cửa sổ cấp cao nhất chứa một khung mà nó in 1:1và trong iframe duy nhất của tài liệu mà nó in 0:1.

Điều này cho phép tiện ích mở rộng của tôi xác định trong cả hai trình duyệt nếu có bất kỳ iframe nào và ngoài ra trong Firefox nếu nó được chạy bên trong một trong các iframe.


1
Hãy thử document.defaultView.self === document.defaultView.tophoặc window !== window.top. Trong tập lệnh nội dung của SDK bổ trợ của Firefox, selfđối tượng toàn cầu là một đối tượng được sử dụng để giao tiếp với tập lệnh chính.
Cướp W

13

Tôi không chắc ví dụ này hoạt động như thế nào đối với các trình duyệt Web cũ hơn nhưng tôi sử dụng nó cho IE, Firefox và Chrome mà không gặp sự cố:

var iFrameDetection = (window === window.parent) ? false : true;

6
Hoặc đơn giản hơn!(window===window.parent)
CalculatorFeline

11
cửa sổ! == window.parent
Ivan Leonenko

5

Tôi đang sử dụng cái này:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);

Tại sao bạn làm điều này : .indexOf("HTMLIFrameElement")?
Lu-ca

.indexOf ('foobarbaz')> -1 là một cách để kiểm tra "kết hợp chuỗi con" (nghĩa là có thể tìm thấy 'foobarbaz' ở đâu đó trong chuỗi?), nhưng không sử dụng các biểu thức thông thường. Nó tương đương về mặt logic với .match (/ foobarbaz /). Nó (được sử dụng để :-) hoạt động trên một phạm vi rộng hơn của trình duyệt và vẫn có thể được sử dụng do thói quen hoặc do lo ngại về hiệu suất của máy móc biểu thức thông thường.
Chuck Kollars

2

Sử dụng chức năng javascript này làm ví dụ về cách thực hiện việc này.

function isNoIframeOrIframeInMyHost() {
// Validation: it must be loaded as the top page, or if it is loaded in an iframe 
// then it must be embedded in my own domain.
// Info: IF top.location.href is not accessible THEN it is embedded in an iframe 
// and the domains are different.
var myresult = true;
try {
    var tophref = top.location.href;
    var tophostname = top.location.hostname.toString();
    var myhref = location.href;
    if (tophref === myhref) {
        myresult = true;
    } else if (tophostname !== "www.yourdomain.com") {
        myresult = false;
    }
} catch (error) { 
  // error is a permission error that top.location.href is not accessible 
  // (which means parent domain <> iframe domain)!
    myresult = false;
}
return myresult;
}

2

Kịch bản phá vỡ khung trình duyệt kế thừa tốt nhất hiện nay

Các giải pháp khác đã không làm việc cho tôi. Cái này hoạt động trên tất cả các trình duyệt:

Một cách để bảo vệ chống lại clickjacking là đưa tập lệnh "bộ ngắt khung" vào mỗi trang không nên đóng khung. Phương pháp sau đây sẽ ngăn trang web không bị đóng khung ngay cả trong các trình duyệt cũ, không hỗ trợ X-Frame-Options-Header.

Trong phần tử HEAD của tài liệu, thêm phần sau:

<style id="antiClickjack">body{display:none !important;}</style>

Đầu tiên áp dụng ID cho chính thành phần kiểu:

<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

Theo cách này, mọi thứ đều có thể nằm trong tài liệu CHÍNH và bạn chỉ cần một phương thức / taglib trong API của mình.

Tham khảo: https://www.codemagi.com/blog/post/194


1
Đóng khung không phải là mối đe dọa duy nhất, về việc phản đối (nghĩa là sử dụng thẻ đối tượng HTML5 thay thế thẻ iframe) .. tôi nghĩ rằng điều này sẽ không hoạt động để chống lại điều đó ..
Raymond Nijland

2
if ( window.location !== window.parent.location ) 
{
      // The page is in an iframe   
} 
else 
{     
      // The page is not in an iframe   
}

1

Vì bạn đang hỏi trong ngữ cảnh của một ứng dụng facebook, bạn có thể muốn xem xét việc phát hiện điều này tại máy chủ khi yêu cầu ban đầu được thực hiện. Facebook sẽ chuyển một loạt dữ liệu chuỗi truy vấn bao gồm khóa fb_sig_user nếu nó được gọi từ iframe.

Vì có thể bạn cần kiểm tra và sử dụng dữ liệu này trong ứng dụng của mình, hãy sử dụng nó để xác định bối cảnh phù hợp để kết xuất.


1

Tôi thực sự đã sử dụng để kiểm tra window.parent và nó hoạt động với tôi, nhưng gần đây cửa sổ là một đối tượng tuần hoàn và luôn có khóa cha, iframe hoặc không có iframe.

Như các ý kiến ​​đề nghị khó so sánh với window.parent công trình. Không chắc chắn nếu điều này sẽ hoạt động nếu iframe chính xác là cùng một trang web với cha mẹ.

window === window.parent;

trong chrome trong bối cảnh cửa sổ chính window.parent === windowlà đúng. Vì vậy, câu trả lời của bạn là không chính xác. Và phần tổng hợp này có thể được sử dụng để kiểm tra (ít nhất là bằng chrome, đã không kiểm tra nó trong các trình duyệt khác).
MarkosyanArtur

KHÔNG LÀM VIỆC trong ngữ cảnh của iFrame, nhưng `if (window === window.parent) {` thì có. Tôi không đánh dấu bạn vì tôi không biết tại sao nó không hoạt động
www-0av-Com

-1

Đó là một đoạn mã cổ mà tôi đã sử dụng một vài lần:

if (parent.location.href == self.location.href) {
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}

Để thêm vào Eneko Alonso: công việc này(parent.location == self.location)
piotr_cz

@piotr_cz, nó chỉ hoạt động nếu chính sách cùng nguồn gốc cho phép truy cập parent.location. Nếu không, một ngoại lệ được ném
Dan

-1

Nếu bạn muốn biết liệu người dùng có truy cập ứng dụng của bạn từ tab trang facebook hay kiểm tra canvas cho Yêu cầu đã ký hay không. Nếu bạn không hiểu, có lẽ người dùng không truy cập từ facebook. Để đảm bảo xác nhận cấu trúc trường và nội dung trường đã ký.

Với php-sdk, bạn có thể nhận được Yêu cầu đã ký như thế này:

$signed_request = $facebook->getSignedRequest();

Bạn có thể đọc thêm về Yêu cầu đã ký tại đây:

https://developers.facebook.com/docs/reference/php/facebook-getSignRequest/

và đây:

https://developers.facebook.com/docs/reference/login/sign-request/


-1

Điều này đã kết thúc là giải pháp đơn giản nhất cho tôi.

    <p id="demofsdfsdfs"></p>

<script>

if(window.self !== window.top) {

//run this code if in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "in frame";

}else{

//run code if not in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "no frame";
}

</script>

-4
if (window.frames.length != parent.frames.length) { page loaded in iframe }

Nhưng chỉ khi số lượng iframe khác nhau trong trang của bạn và trang đang tải bạn trong iframe. Không có iframe trong trang của bạn để đảm bảo 100% kết quả của mã này


Không phải là một giải pháp rất hay để xác định xem cửa sổ có nằm trong iframe hay không và không có gì đảm bảo bạn sẽ có thể đọc từ Parent.frames.
Percy

-4

Viết javascript này trong mỗi trang

if (self == top)
  { window.location = "Home.aspx"; }

Sau đó, nó sẽ tự động chuyển hướng đến trang chủ.


4
Chuyển hướng của bạn sẽ hoạt động khi bạn không nếu khung. Vì vậy, tôi sẽ không thể điều hướng trong trang web của bạn. Thứ hai, các kỹ thuật tồn tại để ngăn chặn chuyển hướng từ trang mẹ.
Marius Balčytis
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.