Как определить, загружается ли веб-страница внутри iframe или непосредственно в окно браузера?
Я пишу приложение на основе iframe facebook. Теперь я хочу использовать ту же html-страницу для отображения обычного веб-сайта, а также страницы canvas в facebook. Я хочу знать, могу ли я определить, была ли страница загружена внутри iframe или непосредственно в браузере?
15 ответов
браузеры могут блокировать доступ к window.top
из-за та же политика происхождения. IE ошибки также имеют место. Вот рабочий код:
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
top
и self
как window
объекты (вместе с parent
), поэтому вы видите, является ли ваше окно верхним окном.
window.frameElement
возвращает элемент (например,
if (window.frameElement) {
// in frame
}
else {
// not in frame
}
Это стандартная и скорее новый метод. он точно работает в Chrome и Firefox. Я не могу рекомендовать его как универсальное решение, но здесь следует упомянуть, я думаю.
Роборг прав,но я хотел добавить примечание.
в IE7 / IE8, когда Microsoft добавила вкладки в свой браузер, они сломали одну вещь, которая вызовет хаос с вашим JS, если вы не будете осторожны.
представьте себе этот макет страницы:
MainPage.html
IframedPage1.html (named "foo")
IframedPage2.html (named "bar")
IframedPage3.html (named "baz")
Теперь в кадре " баз " вы нажимаете ссылку (нет цели, загружается в кадре "баз"), она работает нормально.
Если страница загружается, давайте назовем ее специальной.html, использует JS, чтобы проверить, имеет ли "это" Родительский фрейм с именем "bar" вернет true (ожидаемый).
Теперь давайте скажем, что специальный.html-страница при загрузке проверяет Родительский фрейм (для существования и его имени, и если это "бар", он перезагружается в рамке бара. например,
if(window.parent && window.parent.name == 'bar'){
window.parent.location = self.location;
}
пока все хорошо. Теперь идет ошибка.
давайте скажем вместо нажатия на исходную ссылку, как обычно,и загрузки специального.html-страница в фрейме "baz", вы щелкнули по ней или решили открыть ее в новом Табуляция.
когда эта новая вкладка загружается (без родительских кадров вообще!) IE войдет в бесконечный цикл загрузки страницы! потому что IE "копирует" структуру фрейма в JavaScript, так что новая вкладка имеет родителя, и этот родитель имеет имя "bar".
хорошая новость, это проверка:
if(self == top){
//this returns true!
}
в этой новой вкладке возвращает true, и, таким образом, вы можете проверить это нечетное условие.
принятый ответ не работал для меня внутри сценария содержимого расширения Firefox 6.0 (Addon-SDK 1.0): Firefox выполняет сценарий содержимого в каждом: окне верхнего уровня и во всех iframes.
внутри скрипта содержимого я получаю следующие результаты:
(window !== window.top) : false
(window.self !== window.top) : true
странная вещь об этом выходе заключается в том, что он всегда один и тот же, независимо от того, выполняется ли код внутри iframe или окна верхнего уровня.
С другой стороны Google Chrome кажется, что мой сценарий контента выполняется только один раз в окне верхнего уровня, поэтому выше не будет работать вообще.
что, наконец, сработало для меня в скрипте контента в обоих браузерах:
console.log(window.frames.length + ':' + parent.frames.length);
без iframes это печатает 0:0
в окне верхнего уровня, содержащий один кадр он печатает 1:1
, и в единственном iframe документа он печатает 0:1
.
Это позволяет моему расширению определять в обоих браузерах, есть ли какие-либо iframes присутствующие, и кроме того, в Firefox, если он выполняется внутри одного из фреймов.
Я использую этот:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Я не уверен, как этот пример работает для старых веб-браузеров, но я использую это для IE, Firefox и Chrome без и проблема:
var iFrameDetection = (window === window.parent) ? false : true;
используйте эту функцию 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;
}
поскольку вы спрашиваете в контексте приложения facebook, вы можете рассмотреть возможность обнаружения этого на сервере при первоначальном запросе. Facebook будет передавать кучу данных querystring, включая ключ fb_sig_user, если он вызывается из iframe.
поскольку вам, вероятно, нужно проверить и использовать эти данные в любом случае в вашем приложении, используйте его для определения соответствующего контекста для рендеринга.
лучшие-для-теперь наследие рамка браузера ломать скрипт
другие решения не сработали для меня. Это работает во всех браузерах:
один из способов защиты от clickjacking-включить сценарий "frame-breaker" на каждой странице, который не должен быть обрамлен. Следующая методология предотвратит создание веб-страницы даже в устаревших браузерах, которые не поддерживают заголовок X-Frame-Options.
в элементе головки документа добавьте следующий:
<style id="antiClickjack">body{display:none !important;}</style>
сначала примените идентификатор к самому элементу стиля:
<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
таким образом, все может быть в голове документа, и вам нужен только один метод/taglib в вашем API.
Я на самом деле использовал для проверки окна.parent и это сработало для меня, но в последнее время window является циклическим объектом и всегда имеет Родительский ключ, iframe или нет iframe.
поскольку комментарии предполагают жесткое сравнение с window.родитель работает. Не уверен, что это будет работать, если iframe точно такая же веб-страница, как и родительская.
window === window.parent;
Если вы хотите знать, обращается ли пользователь к вашему приложению с вкладки страницы 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 (parent.location.href == self.location.href) {
window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
if (window.frames.length != parent.frames.length) { page loaded in iframe }
но только если количество iframes отличается на Вашей странице и странице, которые загружают вас в iframe. Не делайте iframe на своей странице, чтобы иметь 100% гарантию результата этого кода
напишите этот javascript на каждой странице
if (self == top)
{ window.location = "Home.aspx"; }
затем он автоматически перенаправляет на главную страницу.