Почему рамочные выключатели работают в междоменном режиме, и можете ли вы условно использовать рамочные выключатели?
Я недавно изучал фрейм, разбивающий код, и столкнулся с каким-то действительно странным поведением, связанным с та же самая политика происхождения, что у меня возникли проблемы с пониманием.
Предположим, у меня есть страница Breaker.html в домене A и страница Container.html в домене B. Примерный код разлома фрейма в Breaker.html, как показано ниже:
if (top !== self) top.location.href = self.location.href;
Это успешно сломает Breaker.html из Container.html, но я не понимаю, зачем это нужно. Из моего чтения той же политики происхождения, top.location
не должен быть доступен вообще, поскольку Container.html находится в другом домене, чем Breaker.html. Даже более странно, кажется, что top.location только для записи:
// Fails if Container.html is on a different domain than Breaker.html
alert(top.location);
Это проблематично для меня, потому что я пытаюсь написать код, который позволяет моей странице находиться в iframe, но только если он находится в том же домене, что и его родительский элемент (или находится в настроенном разрешенном домене). Однако это невозможно определить, так как одна и та же корневая политика запрещает мне доступ к родительскому местоположению.
Итак, у меня есть два вопроса, в основном:
-
Почему код выше этого кода работает вообще?
-
Есть ли способ разорвать фреймы условно или это единственная проверка, которую можно сделать, - это top !== self
? (В частности, я хочу иметь возможность читать домен, чтобы я мог предоставить список допустимых доменов, просто проверяя, находится ли я в том же домене или нет, не будет идеальным.)
Ответы
Ответ 1
В ответ на номер 1: с точки зрения безопасности существует большая разница между доступом для чтения и доступом к записи. Возможность чтения top.location.href является проблемой безопасности. Возможность писать в top.location.href не является.
Что касается ответа на ваш вопрос, я не знаю javascript достаточно хорошо, чтобы быть уверенным, но одна идея заключалась бы в том, чтобы убедиться, что если чтение top.location не выполняется (проверьте исключения), оно находится в другом домене.
Ответ 2
Ответ на вопрос 1 заключается в том, что оператор равенства может использоваться против top.location.href по причинам, связанным с наследием. Breaker.html не может читать top.location.href, но он может сравнить его с другим значением.
Тогда ответ на вопрос 2 не станет, вы должны использовать == == для части, потому что вы не сможете сделать подстроку на top.location.href из перекрестного домена breaker.html.
Я мог ошибаться, но что я понимаю текущий мир iframe.
Ответ 3
Это вопрос номер 2: если вы хотите взять HREF из parent.location(не top.location), вы можете сделать это:
if ((window.top === window.parent) && (history.length==1)) parentHREF=document.referrer;
В основном, что делает этот код:
[1] Проверка, является ли родительский кадр верхней, поскольку вы можете взять только родительский HREF, даже если он не является верхним фреймом.
[2] Проверка того, была ли история iframe пустой, прежде чем загружать ее источник, потому что если нет... document.referrer вернет последний HREF в этой истории фреймов.
После этого вы есть новая проблема: в случае, если значение history.length больше одного, вы можете использовать белый список имен хостов, чтобы проверить, нужно ли его открывать или нет:
if ([location.hostname, 'stackoverflow.com'].indexOf(location.hostname)>=0) hasToBeOpened=true;
Обратите внимание, что у вас есть другая опция: можно использовать целевую страницу, чтобы проверить, открывается ли "первая" страница или нет, используйте этот код:
<head>
<script>
var parentHREF;
if ((window.top === window.parent) && (history.length==1)) parentHREF=document.referrer;
if (/*conditions mentiones above*/) document.write("<META http-equiv='refresh' content='0;URL=http://example.com/go-here.html'>");
</script>
</head>
Выполняя это, первая страница сначала заменит значение истории (в данном случае это первое). Этот код asuming "example.com" является вашим доменом.