programing

웹 페이지가 iframe 내에 로드되어 있는지 브라우저 창에 직접 로드되어 있는지 확인하는 방법

javaba 2022. 10. 27. 23:43
반응형

웹 페이지가 iframe 내에 로드되어 있는지 브라우저 창에 직접 로드되어 있는지 확인하는 방법

iframe 기반의 페이스북 앱을 만들고 있습니다.이제 같은 html 페이지를 사용하여 일반 웹 사이트와 Facebook 내의 캔버스 페이지를 렌더링합니다.페이지가 iframe에 로드되었는지 브라우저에 직접 로드되었는지 확인할 수 있는지 알고 싶습니다.

는 '에 대한 접근을 할 수 있습니다.window.top발신기지 정책이 동일하기 때문입니다.IE의 버그도 발생합니다.작업 코드는 다음과 같습니다.

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

top ★★★★★★★★★★★★★★★★★」self 다이다window 함께)parent창이 맨 위 창인지 확인합니다.

부모와 같은 발신기지 iframe에 있는 경우 메서드는 요소를 반환합니다(예:iframe ★★★★★★★★★★★★★★★★★」object )을합니다). 창이 내장되어 있습니다. 않으면과 자녀 의 기원이 다른 됩니다.null.

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

이것은 모든 최신 브라우저에서 기본을 지원하는 HTML 표준입니다.

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

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

RoBorg는 맞지만, 저는 사이드 노트를 추가하고 싶었습니다.

IE7/IE8에서는 Microsoft가 브라우저에 탭을 추가했을 때 주의하지 않으면 JS에 큰 피해를 줄 수 있는 문제가 발생했습니다.

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

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

이제 프레임 "baz"에서 링크(타깃 없음, "baz" 프레임에 로드)를 클릭하면 정상적으로 작동합니다.

로드된 페이지가 special.html로 불리면 JS를 사용하여 "bar"라는 이름의 부모 프레임이 있는지 확인하고 true를 반환합니다(예상).

이제 special.html 페이지가 로드될 때 부모 프레임(존재 여부 및 이름 확인, "bar"인 경우 막대 프레임에 새로고침됩니다.

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

아직까지는 좋아.이제 문제가 발생했군요.

보통과 같이 원래 링크를 클릭하여 "baz" 프레임에 special.html 페이지를 로드하는 대신 해당 페이지를 미들클릭하거나 새 탭에서 열도록 선택했습니다.

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

좋은 소식은 확인입니다.

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

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

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

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

컨텐츠 스크립트에서는, 다음의 결과를 얻을 수 있습니다.

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

이 출력의 이상한 점은 코드가 iframe 내에서 실행되든 최상위 창에서 실행되든 항상 동일하다는 것입니다.

반면 Google Chrome은 최상위 창에서 콘텐츠 스크립트를 한 번만 실행하는 것 같기 때문에 위의 내용은 전혀 작동하지 않습니다.

두 브라우저의 콘텐츠스크립트에서 마침내 작동하게 된 것은 다음과 같습니다.

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

하지 않으면 iframe이 됩니다.0:0에서는 1개의 프레임이 인쇄됩니다.1:1에 iframe이 0:1.

이것에 의해, 양쪽의 브라우저에 iframe이 존재하는지 어떤지, 파이어폭스에서도 iframe의 어느쪽인가를 실행할지를 판별할 수 있습니다.

이것을 사용하고 있습니다.

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

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

현재로선 최적의 레거시 브라우저 프레임 브레이크 스크립트

다른 해결책은 나에게 효과가 없었다.이 기능은 모든 브라우저에서 작동합니다.

클릭잭킹으로부터 보호하는 한 가지 방법은 프레임화하지 않는 각 페이지에 "frame-breaker" 스크립트를 포함하는 것입니다.다음 방법론은 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에 method/taglib 하나만 있으면 됩니다.

참고 자료: https://www.codemagi.com/blog/post/194

예전에는 window.parent를 체크했는데, 최근에는 window가 순환 객체이기 때문에 iframe 또는 no iframe 부모 키가 항상 있습니다.

window.parent와 비교하기 어려운 코멘트입니다.iframe이 부모 웹 페이지와 완전히 동일한 경우 이 기능이 작동할지 확실하지 않습니다.

window === window.parent;

Facebook 앱의 컨텍스트에서 질문하는 것이기 때문에 최초 요청이 있을 때 서버에서 이를 감지하는 것을 고려해 보는 것이 좋습니다.Facebook은 iframe에서 fb_sig_user 키를 포함한 다수의 쿼리 문자열 데이터를 전달합니다.

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

function amiLoadedInIFrame() {
    try {
         // Introduce a new propery in window.top
         window.top.dummyAttribute = true;
         // If window.dummyAttribute is there.. then window and window.top are same intances
         return !window.dummyAttribute;
    } catch(e) {
         // Exception will be raised when the top is in different domain
         return true;
    }
}

@magnoz가 말한 것에 이어, 그의 답변의 코드 실장을 다음에 나타냅니다.

constructor() {
    let windowLen = window.frames.length;
    let parentLen = parent.frames.length;

    if (windowLen == 0 && parentLen >= 1) {
        this.isInIframe = true
        console.log('Is in Iframe!')
    } else {
        console.log('Is in main window!')
    }
}

이건 제가 몇 번 사용한 고대의 코드입니다.

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

사용자가 Facebook 페이지 탭 또는 캔버스에서 앱에 액세스하고 있는지 알고 싶다면 서명된 요청을 확인하십시오.접속할 수 없는 경우는, 유저가 Facebook 에서 액세스 하고 있지 않을 가능성이 있습니다.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/

이것은 나에게 가장 간단한 해결책으로 끝났다.

    <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>
if (window.frames.length != parent.frames.length) { page loaded in iframe }

다만, iframe 로딩하고 있는 페이지와 iframe 로딩하고 있는 페이지의 iframe 의 수가 다른 경우 뿐입니다.이 코드의 결과를 100% 보장하려면 페이지에 iframe을 설정하지 마십시오.

각 페이지에 이 Javascript를 작성하십시오.

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

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

언급URL : https://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t

반응형