웹 페이지가 iframe 내부 또는 브라우저 창에 직접로드되는지 식별하는 방법은 무엇입니까?


596

iframe 기반 페이스 북 앱을 작성 중입니다. 이제 동일한 HTML 페이지를 사용하여 일반 웹 사이트와 페이스 북의 캔버스 페이지를 렌더링하려고합니다. 페이지가 iframe에로드되었는지 브라우저에 직접로드되었는지 확인할 수 있는지 알고 싶습니다.


2
몇 가지 좋은 방법 (의견 포함) : tommcfarlin.com/check-if-a-page-is-in-i-iframe
simhumileco

답변:


1106

브라우저는 동일한 출처 정책window.top 으로 인해 액세스를 차단할 수 있습니다 . IE 버그도 발생합니다. 작동 코드는 다음과 같습니다.

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

topself둘 다 window객체 parent이므로 창이 맨 위 창인지 확인합니다.


4
이것은 Firefox에서 잘 작동하는 것 같습니다. 다른 브라우저에서도 작동합니까?
akshat

5
부모 iframe이 페이지에 포함되어 있는지 여부를 확인하기 위해 iframe에 iframe이있는 페이지가있는 경우 자식 iframe에서 테스트하기 위해 if (parent === top)
sglessard

7
@sglessard 만약 자식 페이지와 부모가 다른 도메인에 있다면 Firefox는 동일한 출처 정책 (www.w3.org/Security/wiki/Same_Origin_Policy)에 대해 불평하고 코드가 작동하지 않습니다
Gaurang Jadia

18
이것은 IE 11, 10 및 9에서 작동합니다. 또한 FF 및 Opera뿐만 아니라 Chrome에서도 작동합니다. 나는 그것에 관한 문제에 부딪치지 않았다.
jeremysawesome

4
1995 년 최신 기술을 계속 사용하는 사용자 의 경우 , 또는의 내용에서 실행될 때 window.self !== window.top반환 true됩니다 . frame iframe
Jeromy French

84

부모와 같은 원점에서 iframe에있을 때, window.frameElement메소드는 윈도우가 포함 된 요소 (예 : iframe또는 object)를 반환합니다 . 그렇지 않으면 최상위 컨텍스트에서 탐색하거나 상위 프레임과 하위 프레임의 출처가 서로 다른 경우로 평가됩니다 null.

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

모든 최신 브라우저에서 기본적으로 지원 되는 HTML 표준 입니다.


2
W3CframeElement 에 따라 읽기 를 시도하면 교차 출처 iframe에서 SecurityError 예외가 발생합니다 ( WHATWG 는 대신 null을 반환해야한다고 말합니다). 그래서 당신은 그것을 문장 으로 감싸고 싶을 수도 있습니다 . try...catch
Oriol

5
지고 null의 내부와 외부iframe
OlehZiniak

4
MDN 의 설명에 따르면 문서가 포함 된 문서의 출처가 다른 경우 (예 : 다른 도메인에서 찾은 경우)이 문서는 null입니다.
xeophin

수익이 무엇인지 명확히하기 위해 :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

26

RoBorg는 정확하지만 보조 메모를 추가하고 싶었습니다.

IE7 / IE8에서 Microsoft가 브라우저에 탭을 추가했을 때 조심하지 않으면 JS에 혼란을 야기하는 한 가지 문제가 발생했습니다.

이 페이지 레이아웃을 상상해보십시오.

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

이제 "baz"프레임에서 링크를 클릭하십시오 ( "baz"프레임에로드 된 대상 없음).

로드 된 페이지를 special.html로 호출하고 JS를 사용하여 "it"에 "bar"라는 상위 프레임이 있는지 확인하면 true (예상)를 반환합니다.

이제 special.html 페이지가로드 될 때 부모 프레임을 검사하고 (존재 여부와 이름이 "바"인 경우) 바 프레임에 다시로드된다고 가정합니다.

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

여태까지는 그런대로 잘됐다. 이제 버그가 온다.

일반 링크처럼 원래 링크를 클릭하고 "baz"프레임에 special.html 페이지를로드하는 대신 마우스 가운데 버튼을 클릭하거나 새 탭에서 열도록 선택했습니다.

새 탭이로드되면 ( 부모 프레임이 전혀 없습니다! ) IE는 끝없는 페이지 로딩 루프에 들어갑니다! IE가 JavaScript의 프레임 구조를 "복사"하여 새 탭에 부모가 있고 해당 부모에 "bar"라는 이름이 있기 때문입니다.

좋은 소식은 확인하는 것입니다.

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

새 탭에서 true를 반환하므로이 이상한 조건을 테스트 할 수 있습니다.


그동안 버그가 수정 되었습니까? IE8에서는 재생할 수 없습니다. 나는 항상 올바른 것을 얻는다 window.parent.
user123444555621

1
확실하지 않습니다-IE9 이하에서 테스트 스위트를 다시 실행하고 업데이트를 게시합니다.
scunliffe

18

Firefox 6.0 Extension (Addon-SDK 1.0)의 컨텐츠 스크립트에서 허용 된 답변이 작동하지 않았습니다. Firefox는 각각의 최상위 레벨 창과 모든 iframe에서 컨텐츠 스크립트를 실행합니다.

콘텐츠 스크립트 내에서 다음과 같은 결과를 얻습니다.

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

이 출력에 대한 이상한 점은 코드가 iframe에서 실행되는지 아니면 최상위 창에서 실행되는지에 관계없이 항상 동일하다는 것입니다.

반면에 Chrome은 최상위 창 내에서 한 번만 내 콘텐츠 스크립트를 실행하는 것처럼 보이므로 위의 작업은 전혀 작동하지 않습니다.

두 브라우저의 콘텐츠 스크립트에서 마침내 나를 위해 일한 것은 다음과 같습니다.

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

iframe이 없으면 인쇄 0:0되며, 하나의 프레임이 포함 된 최상위 창 1:1에서 인쇄 되며, 문서의 유일한 iframe에서 인쇄 0:1됩니다.

이렇게하면 내 확장 프로그램에 iframe이 있으면 두 브라우저에서, iframe 중 하나에서 실행되는 경우 Firefox에서 추가로 결정할 수 있습니다.


1
document.defaultView.self === document.defaultView.top또는을 시도하십시오 window !== window.top. Firefox의 애드온 SDK의 컨텐츠 스크립트에서 글로벌 self오브젝트는 기본 스크립트와 통신하는 데 사용되는 오브젝트입니다.
Rob W

13

이 예제가 이전 웹 브라우저에서 어떻게 작동하는지 잘 모르겠지만 IE, Firefox 및 Chrome에서 문제없이 사용합니다.

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

6
또는 간단히!(window===window.parent)
CalculatorFeline

11
window! == window.parent
Ivan Leonenko

5

나는 이것을 사용하고있다 :

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

왜 이렇게합니까 : .indexOf("HTMLIFrameElement")?
누가 복음

.indexOf ( 'foobarbaz')> -1은 "하위 문자열 일치"를 확인하는 방법입니다 (예 : 문자열 내 어딘가에서 'foobarbaz'를 찾을 수 있습니까?). 그러나 정규 표현식을 사용하지 않습니다. 논리적으로 .match (/ foobarbaz /)와 같습니다. 그것은 광범위한 브라우저에서 작동하며 습관이 없거나 정규 표현 기계의 성능에 대한 두려움 때문에 여전히 사용될 수 있습니다.
Chuck Kollars

2

이를 수행하는 방법에 대한 예제로이 JavaScript 함수를 사용하십시오.

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

최신 브라우저 브라우저 속보 스크립트

다른 솔루션은 저에게 효과적이지 않았습니다. 이것은 모든 브라우저에서 작동합니다.

클릭 재킹을 방지하는 한 가지 방법은 각 페이지에 프레임 화해서는 안되는 "프레임 차단기"스크립트를 포함시키는 것입니다. 다음 방법은 X-Frame-Options-Header를 지원하지 않는 레거시 브라우저에서도 웹 페이지가 프레임되지 않도록합니다.

문서 HEAD 요소에서 다음을 추가하십시오.

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

먼저 스타일 요소 자체에 ID를 적용하십시오.

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

이런 식으로 모든 것이 문서 HEAD에있을 수 있으며 API에는 메소드 / taglib가 하나만 필요합니다.

참조 : https://www.codemagi.com/blog/post/194


1
프레임이 유일한 위협이되지 않습니다 .. (iframe이 태그를 대체 HTML5 개체 태그를 사용하여 의미) 반대에 대해 그 ..에 대해이하지 않습니다 작업의 생각
레이몬드 Nijland

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

1

페이스 북 앱의 맥락에서 묻기 때문에 초기 요청이있을 때 서버에서이를 감지하는 것이 좋습니다. Facebook은 fb_sig_user 키가 iframe에서 호출되면 fb_sig_user 키를 포함하여 많은 쿼리 문자열 데이터를 전달합니다.

어쨌든 앱에서이 데이터를 확인하고 사용해야하므로이를 사용하여 렌더링 할 적절한 컨텍스트를 결정하십시오.


1

나는 실제로 window.parent를 확인하는 데 사용했고 그것은 나를 위해 일했지만 최근에는 창은 순환 객체이며 항상 부모 키, iframe 또는 iframe이 없습니다.

의견에 따르면 window.parent와 비교하는 것이 좋습니다. iframe이 부모와 동일한 웹 페이지 인 경우 이것이 작동하는지 확실하지 않습니다.

window === window.parent;

메인 윈도우 컨텍스트에서 크롬으로 window.parent === window사실입니다. 그래서 당신의 대답은 틀립니다. 그리고이 비교는 검사에 사용될 수 있습니다 (적어도 크롬에서는 다른 브라우저에서 테스트하지 않았습니다).
MarkosyanArtur

iFrame과 관련하여 작동하지 않지만`if (window === window.parent) {`않습니다. 왜 작동하지 않는지 모르겠습니다
www-0av-Com

-1

몇 번 사용했던 고대 코드입니다.

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

Eneko 알론소에 추가하려면,이 작품(parent.location == self.location)
piotr_cz

@piotr_cz, 동일 출처 정책이에 대한 액세스를 허용하는 경우에만 작동합니다 parent.location. 그렇지 않으면 예외가 발생합니다
Dan

-1

사용자가 페이스 북 페이지 탭 또는 캔버스에서 앱에 액세스하고 있는지 확인하려면 서명 된 요청을 확인하십시오. 얻지 못하면 아마도 사용자가 페이스 북에서 액세스하지 않는 것입니다. signed_request 필드 구조 및 필드 내용을 확인하십시오.

php-sdk를 사용하면 다음과 같이 서명 된 요청을 얻을 수 있습니다.

$signed_request = $facebook->getSignedRequest();

서명 된 요청에 대한 자세한 내용은 여기를 참조하십시오.

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

그리고 여기:

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


-1

이것은 나를 위해 가장 간단한 해결책이되었습니다.

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

그러나 iframe에로드중인 페이지와 페이지에서 iframe 수가 다른 경우에만 가능합니다. 이 코드의 결과를 100 % 보장하도록 페이지에 iframe을 만들지 마십시오.


윈도우가 iframe 내부에 있는지 여부를 결정하는 매우 우아한 해결책은 아니며 parent.frames에서도 읽을 수 있다고 보장하지 않습니다.
퍼시

-4

이 자바 스크립트를 각 페이지에 작성하십시오

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

그런 다음 자동으로 홈페이지로 리디렉션됩니다.


4
프레임이 아닌 경우 리디렉션이 작동합니다. 따라서 귀하의 사이트를 탐색 할 수 없습니다. 둘째, 부모 페이지에서 리디렉션되지 않도록하는 기술이 있습니다.
Marius Balčytis가 14:13
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.