ÐолиÑика «Ðдинакового иÑÑоÑника» (Same Origin) огÑаниÑÐ¸Ð²Ð°ÐµÑ Ð´Ð¾ÑÑÑп окон и ÑÑеймов дÑÑг к дÑÑгÑ.
ÐÐ´ÐµÑ Ð·Ð°ÐºÐ»ÑÑаеÑÑÑ Ð² Ñом, ÑÑо еÑли Ñ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð¾ÑкÑÑÑо две ÑÑÑаниÑÑ: john-smith.com и gmail.com, Ñо Ñ ÑкÑипÑа Ñо ÑÑÑаниÑÑ john-smith.com не бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑи пÑоÑиÑаÑÑ Ð¿Ð¸ÑÑма из gmail.com. Таким обÑазом, задаÑа полиÑики «Ðдинакового иÑÑоÑника» â заÑиÑиÑÑ Ð´Ð°Ð½Ð½Ñе полÑзоваÑÐµÐ»Ñ Ð¾Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ð¹ кÑажи.
ÐолиÑика "Ðдинакового иÑÑоÑника"
Ðва URL имеÑÑ Â«Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñй иÑÑоÑник» в Ñом ÑлÑÑае, еÑли они имеÑÑ ÑовпадаÑÑие пÑоÑокол, домен и поÑÑ.
ÐÑи URL имеÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñй иÑÑоÑник:
http://site.comhttp://site.com/http://site.com/my/page.html
Ð ÑÑи â ÑазнÑе иÑÑоÑники:
http://www.site.com(дÑÑгой домен:www.важен)http://site.org(дÑÑгой домен:.orgважен)https://site.com(дÑÑгой пÑоÑокол:https)http://site.com:8080(дÑÑгой поÑÑ:8080)
ÐолиÑика «Ðдинакового иÑÑоÑника» говоÑиÑ, ÑÑо:
- еÑли Ñ Ð½Ð°Ñ ÐµÑÑÑ ÑÑÑлка на дÑÑгой обÑекÑ
window, напÑимеÑ, на вÑплÑваÑÑее окно, Ñозданное Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑwindow.openили наwindowиз<iframe>и Ñ ÑÑого окна ÑÐ¾Ñ Ð¶Ðµ иÑÑоÑник, Ñо к Ð½ÐµÐ¼Ñ Ð±ÑÐ´ÐµÑ Ð¿Ð¾Ð»Ð½Ñй доÑÑÑп. - в пÑоÑивном ÑлÑÑае, еÑли Ñ Ð½ÐµÐ³Ð¾ дÑÑгой иÑÑоÑник, Ð¼Ñ Ð½Ðµ Ñможем обÑаÑаÑÑÑÑ Ðº его пеÑеменнÑм, обÑекÑÑ
documentи Ñак далее. ÐдинÑÑвенное иÑклÑÑение â обÑекÑlocation: его можно изменÑÑÑ (Ñаким обÑазом пеÑенапÑавлÑÑ Ð¿Ð¾Ð»ÑзоваÑелÑ). Ðо нелÑÐ·Ñ ÑиÑаÑÑlocation(нелÑÐ·Ñ ÑзнаÑÑ, где Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð¿Ð¾Ð»ÑзоваÑелÑ, ÑÑÐ¾Ð±Ñ Ð½Ðµ бÑло Ð½Ð¸ÐºÐ°ÐºÐ¸Ñ ÑÑеÑек инÑоÑмаÑии).
ÐоÑÑÑп к ÑодеÑÐ¶Ð¸Ð¼Ð¾Ð¼Ñ Ð¸ÑÑейма
ÐнÑÑÑи <iframe> наÑ
одиÑÑÑ Ð¿Ð¾ ÑÑÑи оÑделÑное окно Ñ ÑобÑÑвеннÑми обÑекÑами document и window.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ обÑаÑаÑÑÑÑ Ðº ним, иÑполÑзÑÑ ÑвойÑÑва:
iframe.contentWindowÑÑÑлка на обÑекÑwindowвнÑÑÑи<iframe>.iframe.contentDocumentâ ÑÑÑлка на обÑекÑdocumentвнÑÑÑи<iframe>, коÑоÑÐºÐ°Ñ Ð·Ð°Ð¿Ð¸ÑÑ Ð´Ð»Ñiframe.contentWindow.document.
Ðогда Ð¼Ñ Ð¾Ð±ÑаÑаемÑÑ Ðº вÑÑÑÐ¾ÐµÐ½Ð½Ð¾Ð¼Ñ Ð² иÑÑейм окнÑ, бÑаÑÐ·ÐµÑ Ð¿ÑовеÑÑеÑ, Ð¸Ð¼ÐµÐµÑ Ð»Ð¸ иÑÑейм ÑÐ¾Ñ Ð¶Ðµ иÑÑоÑник. ÐÑли ÑÑо не Ñак, Ñогда доÑÑÑп бÑÐ´ÐµÑ Ð·Ð°Ð¿ÑеÑÑн (ÑазÑеÑена лиÑÑ Ð·Ð°Ð¿Ð¸ÑÑ Ð² location, ÑÑо иÑклÑÑение).
ÐÐ»Ñ Ð¿ÑимеÑа давайÑе попÑобÑем ÑÑение и запиÑÑ Ð² иÑÑейм Ñ Ð´ÑÑгим иÑÑоÑником:
<iframe src="https://example.com" id="iframe"></iframe>
<script>
iframe.onload = function() {
// можно полÑÑиÑÑ ÑÑÑÐ»ÐºÑ Ð½Ð° внÑÑÑенний window
let iframeWindow = iframe.contentWindow; // OK
// ...но пÑи попÑÑке полÑÑиÑÑ Ð´Ð¾ÑÑÑп к document ÑÑÑаниÑÑ
let doc = iframe.contentDocument; // ...полÑÑим null
// Ñакже Ð¼Ñ Ð½Ðµ можем пÑоÑиÑаÑÑ URL ÑÑÑаниÑÑ Ð² иÑÑейме
try {
// нелÑÐ·Ñ ÑиÑаÑÑ Ð¸Ð· обÑекÑа Location
let href = iframe.contentWindow.location.href; // ÐШÐÐÐÐ
} catch(e) {
alert(e); // Security Error
}
// ...но можно пиÑаÑÑ Ð² него (и загÑÑзиÑÑ ÑÑо-Ñо дÑÑгое в иÑÑейм)!
iframe.contentWindow.location = '/'; // OK
iframe.onload = null; // ÑбеÑÑм обÑабоÑÑик, ÑÑÐ¾Ð±Ñ Ð½Ðµ ÑÑабаÑÑвал поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ location
};
</script>
Ðод вÑÑе вÑÐ²ÐµÐ´ÐµÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð¸Ð»Ð¸ null Ð´Ð»Ñ Ð»ÑбÑÑ
опеÑаÑий, кÑоме:
- ÐолÑÑÐµÐ½Ð¸Ñ ÑÑÑлки на внÑÑÑенний обÑекÑ
windowизiframe.contentWindow - ÐзменениÑ
location.
С дÑÑгой ÑÑоÑонÑ, еÑли Ñ Ð¸ÑÑейма ÑÐ¾Ñ Ð¶Ðµ иÑÑоÑник, Ñо Ñ Ð½Ð¸Ð¼ можно делаÑÑ Ð²ÑÑ, ÑÑо Ñгодно:
<!-- иÑÑейм Ñ Ñого же ÑайÑа -->
<iframe src="/" id="iframe"></iframe>
<script>
iframe.onload = function() {
// делаем Ñ Ð½Ð¸Ð¼ ÑÑо Ñгодно
iframe.contentDocument.body.prepend("ÐÑивеÑ, миÑ!");
};
</script>
iframe.onload и iframe.contentWindow.onloadСобÑÑие iframe.onload â по ÑÑÑи Ñо же, ÑÑо и iframe.contentWindow.onload. Ðно ÑÑабоÑаеÑ, когда вÑÑÑоенное окно полноÑÑÑÑ Ð·Ð°Ð³ÑÑзиÑÑÑ Ñо вÑеми ÑеÑÑÑÑами.
â¦Ðо iframe.onload вÑегда доÑÑÑпно извне иÑÑейма, в Ñо вÑÐµÐ¼Ñ ÐºÐ°Ðº доÑÑÑп к iframe.contentWindow.onload ÑазÑеÑÑн ÑолÑко из окна Ñ Ñем же иÑÑоÑником.
Ðкна на Ð¿Ð¾Ð´Ð´Ð¾Ð¼ÐµÐ½Ð°Ñ : document.domain
Ðо опÑеделениÑ, еÑли Ñ Ð´Ð²ÑÑ URL ÑазнÑй домен, Ñо Ñ Ð½Ð¸Ñ ÑазнÑй иÑÑоÑник.
Ðо еÑли в окнаÑ
оÑкÑÑÑÑ ÑÑÑаниÑÑ Ñ Ð¿Ð¾Ð´Ð´Ð¾Ð¼ÐµÐ½Ð¾Ð² одного домена 2-го ÑÑовнÑ, напÑÐ¸Ð¼ÐµÑ john.site.com, peter.site.com и site.com (Ñак ÑÑо иÑ
обÑий домен site.com), Ñо можно заÑÑавиÑÑ Ð±ÑаÑÐ·ÐµÑ Ð¸Ð³Ð½Ð¾ÑиÑоваÑÑ ÑÑо оÑлиÑие. Так ÑÑо бÑаÑÐ·ÐµÑ ÑÐ¼Ð¾Ð¶ÐµÑ ÑÑиÑаÑÑ Ð¸Ñ
пÑиÑедÑими Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ иÑÑоÑника пÑи пÑовеÑке возможноÑÑи доÑÑÑпа дÑÑг к дÑÑгÑ.
ÐÐ»Ñ ÑÑого в каждом Ñаком окне нÑжно запÑÑÑиÑÑ:
document.domain = 'site.com';
ÐоÑле ÑÑого они ÑмогÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð´ÐµÐ¹ÑÑвоваÑÑ Ð±ÐµÐ· огÑаниÑений. ÐÑÑ Ñаз замеÑим, ÑÑо ÑÑо доÑÑÑпно ÑолÑко Ð´Ð»Ñ ÑÑÑÐ°Ð½Ð¸Ñ Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñм доменом вÑоÑого ÑÑовнÑ.
ÐÑÑейм: подождиÑе докÑменÑ
Ðогда иÑÑейм â Ñ Ñого же иÑÑоÑника, Ð¼Ñ Ð¸Ð¼ÐµÐµÐ¼ доÑÑÑп к докÑменÑÑ Ð² нÑм. Ðо еÑÑÑ Ð¿Ð¾Ð´Ð²Ð¾Ñ . Ðе ÑвÑзаннÑй Ñ ÐºÑоÑÑ-доменнÑми оÑобенноÑÑÑми, но доÑÑаÑоÑно важнÑй, ÑÑÐ¾Ð±Ñ Ð¾ нÑм знаÑÑ.
Ðогда иÑÑейм Ñоздан, в нÑм ÑÑÐ°Ð·Ñ ÐµÑÑÑ Ð´Ð¾ÐºÑменÑ. Ðо ÑÑÐ¾Ñ Ð´Ð¾ÐºÑÐ¼ÐµÐ½Ñ â дÑÑгой, не ÑоÑ, коÑоÑÑй в него бÑÐ´ÐµÑ Ð·Ð°Ð³ÑÑжен!
Так ÑÑо еÑли Ð¼Ñ ÑÑÑ Ð¶Ðµ Ñделаем ÑÑо-Ñо Ñ ÑÑим докÑменÑом, Ñо наÑи изменениÑ, ÑкоÑее вÑего, пÑопадÑÑ.
ÐоÑ, взглÑниÑе:
<iframe src="/" id="iframe"></iframe>
<script>
let oldDoc = iframe.contentDocument;
iframe.onload = function() {
let newDoc = iframe.contentDocument;
// загÑÑженнÑй document - не ÑоÑ, коÑоÑÑй бÑл в iframe пÑи Ñоздании изнаÑалÑно!
alert(oldDoc == newDoc); // false
};
</script>
Ðам не ÑледÑÐµÑ ÑабоÑаÑÑ Ñ Ð´Ð¾ÐºÑменÑом еÑÑ Ð½Ðµ загÑÑженного иÑÑейма, Ñак как ÑÑо не ÑÐ¾Ñ Ð´Ð¾ÐºÑменÑ. ÐÑли Ð¼Ñ Ð¿Ð¾ÑÑавим на него обÑабоÑÑики ÑобÑÑий â они бÑдÑÑ Ð¿ÑоигноÑиÑованÑ.
Ðак поймаÑÑ Ð¼Ð¾Ð¼ÐµÐ½Ñ, когда поÑвиÑÑÑ Ð¿ÑавилÑнÑй докÑменÑ?
ÐÑавилÑнÑй докÑÐ¼ÐµÐ½Ñ ÑоÑно бÑÐ´ÐµÑ Ð´Ð¾ÑÑÑпен, когда ÑÑабоÑÐ°ÐµÑ iframe.onload. Ðо он ÑÑабаÑÑÐ²Ð°ÐµÑ ÑолÑко Ñогда, когда загÑÑзиÑÑÑ Ð²ÐµÑÑ Ð¸ÑÑейм Ñо вÑеми его ÑеÑÑÑÑами.
Ðожно пÑовеÑÑÑÑ ÑеÑез setInterval:
<iframe src="/" id="iframe"></iframe>
<script>
let oldDoc = iframe.contentDocument;
// каждÑй 100 Ð¼Ñ Ð¿ÑовеÑÑем, не изменилÑÑ Ð»Ð¸ докÑменÑ
let timer = setInterval(() => {
let newDoc = iframe.contentDocument;
if (newDoc == oldDoc) return;
alert("New document is here!");
clearInterval(timer); // оÑклÑÑим setInterval, он нам болÑÑе не нÑжен
}, 100);
</script>
ÐоллекÑÐ¸Ñ window.frames
ÐÑÑгой ÑпоÑоб полÑÑиÑÑ Ð¾Ð±ÑÐµÐºÑ window из <iframe> â забÑаÑÑ ÐµÐ³Ð¾ из именованной коллекÑии window.frames:
- Ðо номеÑÑ:
window.frames[0]â обÑекÑwindowÐ´Ð»Ñ Ð¿ÐµÑвого ÑÑейма в докÑменÑе. - Ðо имени:
window.frames.iframeNameâ обÑекÑwindowÐ´Ð»Ñ ÑÑейма Ñо ÑвойÑÑвомname="iframeName".
ÐапÑимеÑ:
<iframe src="/" style="height:80px" name="win" id="iframe"></iframe>
<script>
alert(iframe.contentWindow == frames[0]); // true
alert(iframe.contentWindow == frames.win); // true
</script>
ÐÑÑейм Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼ÐµÑÑ Ð´ÑÑгие иÑÑÐµÐ¹Ð¼Ñ Ð²Ð½ÑÑÑи. Таким обÑазом, обÑекÑÑ window ÑоздаÑÑ Ð¸ÐµÑаÑÑ
иÑ.
ÐавигаÑÐ¸Ñ Ð¿Ð¾ ним вÑглÑÐ´Ð¸Ñ Ñак:
window.framesâ коллекÑÐ¸Ñ Â«Ð´Ð¾ÑеÑÐ½Ð¸Ñ Â»window(Ð´Ð»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½ÑÑ ÑÑеймов).window.parentâ ÑÑÑлка на «ÑодиÑелÑÑкий» (внеÑний)window.window.topâ ÑÑÑлка на Ñамого веÑÑ Ð½ÐµÐ³Ð¾ ÑодиÑелÑ.
ÐапÑимеÑ:
window.frames[0].parent === window; // true
Ðожно иÑполÑзоваÑÑ ÑвойÑÑво top, ÑÑÐ¾Ð±Ñ Ð¿ÑовеÑÑÑÑ, оÑкÑÑÑ Ð»Ð¸ ÑекÑÑий докÑÐ¼ÐµÐ½Ñ Ð²Ð½ÑÑÑи иÑÑейма или неÑ:
if (window == top) { // ÑекÑÑий window == window.top?
alert('СкÑÐ¸Ð¿Ñ Ð½Ð°Ñ
одиÑÑÑ Ð² Ñамом веÑÑ
нем обÑекÑе window, не во ÑÑейме');
} else {
alert('СкÑÐ¸Ð¿Ñ Ð·Ð°Ð¿ÑÑен во ÑÑейме!');
}
ÐÑÑибÑÑ Ð¸ÑÑейма sandbox
ÐÑÑибÑÑ sandbox позволÑÐµÑ Ð½Ð°Ð»Ð¾Ð¶Ð¸ÑÑ Ð¾Ð³ÑаниÑÐµÐ½Ð¸Ñ Ð½Ð° дейÑÑÐ²Ð¸Ñ Ð²Ð½ÑÑÑи <iframe>, ÑÑÐ¾Ð±Ñ Ð¿ÑедоÑвÑаÑиÑÑ Ð²Ñполнение ненадÑжного кода. ÐÑÑибÑÑ Ð¿Ð¾Ð¼ÐµÑÐ°ÐµÑ Ð¸ÑÑейм в «пеÑоÑниÑÑ», оÑмеÑÐ°Ñ ÐµÐ³Ð¾ как имеÑÑий дÑÑгой иÑÑоÑник и/или накладÑÐ²Ð°Ñ Ð½Ð° него дополниÑелÑнÑе огÑаниÑениÑ.
СÑÑеÑÑвÑÐµÑ ÑпиÑок «по ÑмолÑаниÑ» огÑаниÑений, коÑоÑÑе накладÑваÑÑÑÑ Ð½Ð° <iframe sandbox src="...">. ÐÑ
можно ÑменÑÑиÑÑ, еÑли ÑказаÑÑ Ð² аÑÑибÑÑе ÑпиÑок иÑклÑÑений (ÑпеÑиалÑнÑми клÑÑевÑми Ñловами), коÑоÑÑе не нÑжно пÑименÑÑÑ, напÑимеÑ: <iframe sandbox="allow-forms allow-popups">.
ÐÑÑгими Ñловами, еÑли Ñ Ð°ÑÑибÑÑа "sandbox" Ð½ÐµÑ Ð·Ð½Ð°ÑениÑ, Ñо бÑаÑÐ·ÐµÑ Ð¿ÑименÑÐµÑ Ð¼Ð°ÐºÑимÑм огÑаниÑений, но ÑеÑез пÑобел можно ÑказаÑÑ Ñе из ниÑ
, коÑоÑÑе Ð¼Ñ Ð½Ðµ Ñ
оÑим пÑименÑÑÑ.
ÐÐ¾Ñ ÑпиÑок огÑаниÑений:
allow-same-origin"sandbox"пÑинÑдиÑелÑно ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Â«Ð´ÑÑгой иÑÑоÑник» Ð´Ð»Ñ Ð¸ÑÑейма. ÐÑÑгими Ñловами, он заÑÑавлÑÐµÑ Ð±ÑаÑÐ·ÐµÑ Ð²Ð¾ÑпÑинимаÑÑiframe, как пÑиÑедÑий из дÑÑгого иÑÑоÑника, даже еÑлиsrcÑодеÑÐ¶Ð¸Ñ ÑÐ¾Ñ Ð¶Ðµ ÑайÑ. Со вÑеми ÑопÑÑÑÑвÑÑÑими огÑаниÑениÑми Ð´Ð»Ñ ÑкÑипÑов. ÐÑа опÑÐ¸Ñ Ð¾ÑклÑÑÐ°ÐµÑ ÑÑо огÑаниÑение.allow-top-navigation- ÐозволÑÐµÑ Ð¸ÑÑÐµÐ¹Ð¼Ñ Ð¼ÐµÐ½ÑÑÑ
parent.location. allow-forms- ÐозволÑÐµÑ Ð¾ÑпÑавлÑÑÑ ÑоÑÐ¼Ñ Ð¸Ð· иÑÑейма.
allow-scripts- ÐозволÑÐµÑ Ð·Ð°Ð¿ÑÑкаÑÑ ÑкÑипÑÑ Ð¸Ð· иÑÑейма.
allow-popups- ÐозволÑÐµÑ Ð¾ÑкÑÑваÑÑ Ð²ÑплÑваÑÑие окна из иÑÑейма Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ
window.open.
ÐолÑÑе опÑий можно найÑи в ÑпÑавоÑнике.
ÐÑÐ¸Ð¼ÐµÑ Ð½Ð¸Ð¶Ðµ демонÑÑÑиÑÑÐµÑ Ð¸ÑÑейм, помеÑÑннÑй в пеÑоÑниÑÑ Ñо ÑÑандаÑÑнÑм набоÑом огÑаниÑений: <iframe sandbox src="...">. Ðа ÑÑÑаниÑе ÑодеÑжиÑÑÑ JavaScript и ÑоÑма.
ÐбÑаÑиÑе внимание, ÑÑо ниÑего не ÑабоÑаеÑ. Таким обÑазом, Ð½Ð°Ð±Ð¾Ñ Ð¾Ð³ÑаниÑений по ÑмолÑÐ°Ð½Ð¸Ñ Ð¾ÑÐµÐ½Ñ ÑÑÑогий:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div>ÐÑÑейм ниже Ð¸Ð¼ÐµÐµÑ Ð°ÑÑибÑÑ <code>sandbox</code>.</div>
<iframe sandbox src="sandboxed.html" style="height:60px;width:90%"></iframe>
</body>
</html><!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<button onclick="alert(123)">ÐажмиÑе Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка ÑкÑипÑа (не ÑÑабоÑаеÑ)</button>
<form action="http://google.com">
<input type="text">
<input type="submit" value="ÐÑпÑавиÑÑ (не ÑÑабоÑаеÑ)">
</form>
</body>
</html>ÐÑÑибÑÑ "sandbox" Ñоздан ÑолÑко Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑ Ð¾Ð³ÑаниÑениÑ. Ðн не Ð¼Ð¾Ð¶ÐµÑ ÑдалÑÑÑ Ð¸Ñ
. Ð ÑаÑÑноÑÑи, он не Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑлабиÑÑ Ð¾Ð³ÑаниÑениÑ, накладÑваемÑе бÑаÑзеÑом на иÑÑейм, пÑиÑ
одÑÑий Ñ Ð´ÑÑгого иÑÑоÑника.
Ðбмен ÑообÑениÑми Ð¼ÐµÐ¶Ð´Ñ Ð¾ÐºÐ½Ð°Ð¼Ð¸
ÐнÑеÑÑÐµÐ¹Ñ postMessage позволÑÐµÑ Ð¾ÐºÐ½Ð°Ð¼ обÑаÑÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ñобой незавиÑимо Ð¾Ñ Ð¸Ñ
пÑоиÑÑ
ождениÑ.
ÐÑо ÑпоÑоб обойÑи полиÑÐ¸ÐºÑ Â«Ðдинакового иÑÑоÑника». Ðн позволÑÐµÑ Ð¾Ð±Ð¼ÐµÐ½Ð¸Ð²Ð°ÑÑÑÑ Ð¸Ð½ÑоÑмаÑией, Ñкажем john-smith.com и gmail.com, но ÑолÑко в Ñом ÑлÑÑае, еÑли оба ÑайÑа ÑоглаÑÐ½Ñ Ð¸ вÑзÑваÑÑ ÑооÑвеÑÑÑвÑÑÑие JavaScript-ÑÑнкÑии. ÐÑо Ð´ÐµÐ»Ð°ÐµÑ Ð¾Ð±Ñение безопаÑнÑм Ð´Ð»Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ.
ÐнÑеÑÑÐµÐ¹Ñ Ð¸Ð¼ÐµÐµÑ Ð´Ð²Ðµ ÑаÑÑи.
postMessage
Ðкно, коÑоÑое Ñ
оÑÐµÑ Ð¾ÑпÑавиÑÑ ÑообÑение, должно вÑзваÑÑ Ð¼ÐµÑод postMessage окна полÑÑаÑелÑ. ÐÑÑгими Ñловами, еÑли Ð¼Ñ Ñ
оÑим оÑпÑавиÑÑ ÑообÑение в окно win, Ñогда нам ÑледÑÐµÑ Ð²ÑзваÑÑ win.postMessage(data, targetOrigin).
ÐÑгÑменÑÑ:
data- ÐаннÑе Ð´Ð»Ñ Ð¾ÑпÑавки. ÐÐ¾Ð¶ÐµÑ Ð±ÑÑÑ Ð»ÑбÑм обÑекÑом, даннÑе клониÑÑÑÑÑÑ Ñ Ð¸ÑполÑзованием «алгоÑиÑма ÑÑÑÑкÑÑÑиÑованного клониÑованиÑ». IE поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑолÑко ÑÑÑоки, поÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸ÑполÑзоваÑÑ Ð¼ÐµÑод
JSON.stringifyна ÑложнÑÑ Ð¾Ð±ÑекÑÐ°Ñ , ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ð´ÐµÑжаÑÑ ÑÑÐ¾Ñ Ð±ÑаÑзеÑ. targetOrigin- ÐпÑеделÑÐµÑ Ð¸ÑÑоÑник Ð´Ð»Ñ Ð¾ÐºÐ½Ð°-полÑÑаÑелÑ, ÑолÑко окно Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ иÑÑоÑника Ð¸Ð¼ÐµÐµÑ Ð¿Ñаво полÑÑиÑÑ ÑообÑение.
Указание targetOrigin ÑвлÑеÑÑÑ Ð¼ÐµÑой безопаÑноÑÑи. Ðак Ð¼Ñ Ð¿Ð¾Ð¼Ð½Ð¸Ð¼, еÑли окно (полÑÑаÑелÑ) пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¸Ð· дÑÑгого иÑÑоÑника, Ð¼Ñ Ð¸Ð· окна-оÑпÑавиÑÐµÐ»Ñ Ð½Ðµ можем пÑоÑиÑаÑÑ ÐµÐ³Ð¾ location. Таким обÑазом, Ð¼Ñ Ð½Ðµ можем бÑÑÑ ÑвеÑенÑ, какой ÑÐ°Ð¹Ñ Ð¾ÑкÑÑÑ Ð² заданном окне пÑÑмо ÑейÑаÑ: полÑзоваÑÐµÐ»Ñ Ð¼Ð¾Ð³ пеÑейÑи кÑда-Ñо, окно-оÑпÑавиÑÐµÐ»Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ ÑÑо знаÑÑ.
ÐÑли ÑказаÑÑ targetOrigin, Ñо Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ бÑÑÑ ÑвеÑенÑ, ÑÑо окно полÑÑÐ¸Ñ Ð´Ð°Ð½Ð½Ñе ÑолÑко в Ñом ÑлÑÑае, еÑли в нÑм пÑавилÑнÑй ÑайÑ. ÐÑобенно ÑÑо важно, еÑли даннÑе конÑиденÑиалÑнÑе.
ÐапÑимеÑ, здеÑÑ win полÑÑÐ¸Ñ ÑообÑÐµÐ½Ð¸Ñ ÑолÑко в Ñом ÑлÑÑае, еÑли в нÑм оÑкÑÑÑ Ð´Ð¾ÐºÑÐ¼ÐµÐ½Ñ Ð¸Ð· иÑÑоÑника http://example.com:
<iframe src="http://example.com" name="example">
<script>
let win = window.frames.example;
win.postMessage("message", "http://example.com");
</script>
ÐÑли Ð¼Ñ Ð½Ðµ Ñ
оÑим пÑовеÑÑÑÑ, Ñо в targetOrigin можно ÑказаÑÑ *.
<iframe src="http://example.com" name="example">
<script>
let win = window.frames.example;
win.postMessage("message", "*");
</script>
СобÑÑие message
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑаÑÑ ÑообÑениÑ, окно-полÑÑаÑÐµÐ»Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ имеÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑÐ¸Ñ message (ÑообÑение). Ðно ÑÑабаÑÑваеÑ, когда бÑл вÑзван меÑод postMessage (и пÑовеÑка targetOrigin пÑойдена ÑÑпеÑно).
ÐбÑÐµÐºÑ ÑобÑÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ ÑпеÑиÑиÑнÑе ÑвойÑÑва:
data- ÐаннÑе из
postMessage. origin- ÐÑÑоÑник оÑпÑавиÑелÑ, напÑимеÑ,
http://javascript.info. source- СÑÑлка на окно-оÑпÑавиÑелÑ. Ðожно ÑÑÐ°Ð·Ñ Ð¾ÑпÑавиÑÑ ÑÑо-Ñо в оÑвеÑ, вÑзвав
source.postMessage(...).
ЧÑÐ¾Ð±Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ð¾Ð±ÑабоÑÑик, ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð¼ÐµÑод addEventListener, коÑоÑкий ÑинÑакÑÐ¸Ñ window.onmessage не ÑабоÑаеÑ.
ÐÐ¾Ñ Ð¿ÑимеÑ:
window.addEventListener("message", function(event) {
if (event.origin != 'http://javascript.info') {
// ÑÑо-Ñо пÑиÑло Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑÑного домена. ÐавайÑе пÑоигноÑиÑÑем ÑÑо
return;
}
alert( "received: " + event.data );
// can message back using event.source.postMessage(...)
});
ÐолнÑй пÑимеÑ:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
ÐолÑÑение иÑÑейма.
<script>
window.addEventListener('message', function(event) {
alert(`ÐолÑÑено ${event.data} из ${event.origin}`);
});
</script>
</body>
</html><!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form id="form">
<input type="text" placeholder="ÐведиÑе ÑообÑение" name="message">
<input type="submit" value="ÐажмиÑе Ð´Ð»Ñ Ð¾ÑпÑавки">
</form>
<iframe src="iframe.html" id="iframe" style="display:block;height:60px"></iframe>
<script>
form.onsubmit = function() {
iframe.contentWindow.postMessage(this.message.value, '*');
return false;
};
</script>
</body>
</html>ÐÐµÐ¶Ð´Ñ postMessage и ÑобÑÑием message не ÑÑÑеÑÑвÑÐµÑ Ð·Ð°Ð´ÐµÑжки. СобÑÑие пÑоиÑÑ
Ð¾Ð´Ð¸Ñ ÑинÑ
Ñонно, бÑÑÑÑее, Ñем setTimeout(...,0).
ÐÑого
ЧÑÐ¾Ð±Ñ Ð²ÑзваÑÑ Ð¼ÐµÑод или полÑÑиÑÑ ÑодеÑжимое из дÑÑгого окна, нам, во-пеÑвÑÑ , Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ имеÑÑ ÑÑÑÐ»ÐºÑ Ð½Ð° него.
ÐÐ»Ñ Ð²ÑплÑваÑÑÐ¸Ñ Ð¾ÐºÐ¾Ð½ (попапов) доÑÑÑÐ¿Ð½Ñ ÑÑÑлки в обе ÑÑоÑонÑ:
- ÐÑи оÑкÑÑÑии окна:
window.openоÑкÑÑÐ²Ð°ÐµÑ Ð½Ð¾Ð²Ð¾Ðµ окно и возвÑаÑÐ°ÐµÑ ÑÑÑÐ»ÐºÑ Ð½Ð° него, - ÐзнÑÑÑи оÑкÑÑÑого окна:
window.openerâ ÑÑÑлка на оÑкÑÑваÑÑее окно.
ÐÐ»Ñ Ð¸ÑÑеймов Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ имеÑÑ Ð´Ð¾ÑÑÑп к ÑодиÑелÑм/поÑомкам, иÑполÑзÑÑ:
window.framesâ коллекÑÐ¸Ñ Ð¾Ð±ÑекÑовwindowвложеннÑÑ Ð¸ÑÑеймов,window.parent,window.topâ ÑÑо ÑÑÑлки на ÑодиÑелÑÑкое окно и окно Ñамого веÑÑ Ð½ÐµÐ³Ð¾ ÑÑовнÑ,iframe.contentWindowâ ÑÑо обÑекÑwindowвнÑÑÑи Ñега<iframe>.
ÐÑли окна имеÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñй иÑÑоÑник (пÑоÑокол, домен, поÑÑ), Ñо они могÑÑ Ð´ÐµÐ»Ð°ÑÑ Ð´ÑÑг Ñ Ð´ÑÑгом вÑÑ, ÑÑо Ñгодно.
РпÑоÑивном ÑлÑÑае Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ ÑолÑко ÑледÑÑÑие дейÑÑвиÑ:
- Ðзменение ÑвойÑÑва location дÑÑгого окна (доÑÑÑп ÑолÑко на запиÑÑ).
- ÐÑпÑавиÑÑ ÑÑда ÑообÑение.
ÐÑклÑÑениÑ:
- Ðкна, коÑоÑÑе имеÑÑ Ð¾Ð±Ñий домен вÑоÑого ÑÑовнÑ:
a.site.comиb.site.com. УÑÑановка ÑвойÑÑваdocument.domain='site.com'в Ð¾Ð±Ð¾Ð¸Ñ Ð¾ÐºÐ½Ð°Ñ Ð¿ÐµÑеведÑÑ Ð¸Ñ Ð² ÑоÑÑоÑние «Ðдинакового иÑÑоÑника». - ÐÑли Ñ Ð¸ÑÑейма ÑÑÑановлен аÑÑибÑÑ
sandbox, ÑÑо пÑинÑдиÑелÑно пеÑеведÑÑ Ð¾ÐºÐ½Ð° в ÑоÑÑоÑние «ÑазнÑÑ Ð¸ÑÑоÑников», еÑли не ÑÑÑановиÑÑ Ð² аÑÑибÑÑ Ð·Ð½Ð°Ñениеallow-same-origin. ÐÑо можно иÑполÑзоваÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка ненадÑжного кода в иÑÑейме Ñ Ñого же ÑайÑа.
ÐеÑод postMessage позволÑÐµÑ Ð¾Ð±ÑаÑÑÑÑ Ð´Ð²Ñм окнам Ñ Ð»ÑбÑми иÑÑоÑниками:
-
ÐÑпÑавиÑÐµÐ»Ñ Ð²ÑзÑваеÑ
targetWin.postMessage(data, targetOrigin). -
ÐÑли
targetOriginне'*', Ñогда бÑаÑÐ·ÐµÑ Ð¿ÑовеÑÑÐµÑ Ð¸Ð¼ÐµÐµÑ Ð»Ð¸targetWinиÑÑоÑникtargetOrigin. -
ÐÑли ÑÑо Ñак, Ñогда
targetWinвÑзÑÐ²Ð°ÐµÑ ÑобÑÑиеmessageÑо ÑпеÑиалÑнÑми ÑвойÑÑвами:originâ иÑÑоÑник окна оÑпÑавиÑÐµÐ»Ñ (напÑимеÑ,http://my.site.com)sourceâ ÑÑÑлка на окно оÑпÑавиÑелÑ.dataâ даннÑе, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð±ÑекÑом везде, кÑоме IE (в IE ÑолÑко ÑÑÑоки).
Рокне-полÑÑаÑеле ÑледÑÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ð¾Ð±ÑабоÑÑик Ð´Ð»Ñ ÑÑого ÑобÑÑÐ¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¼ÐµÑода
addEventListener.

ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)