Questo è come:
Per la condivisione tra i sottodomini di un determinato superdominio (ad esempio example.com), esiste una tecnica che puoi utilizzare in quella situazione. Esso può essere applicato a localStorage
, IndexedDB
, SharedWorker
, BroadcastChannel
, ecc, tutti che offrono funzionalità condivise tra le pagine dello stesso di origine, ma per qualche motivo non rispetta alcuna modificadocument.domain
che avrebbe permesso loro di utilizzare l'superdominio loro origine direttamente.
(1) Scegli un dominio "principale" a cui appartengono i dati: ad esempio, https://example.com o https://www.example.com manterranno i tuoi dati localStorage. Supponiamo che tu scelga https://example.com .
(2) Usa localStorage normalmente per le pagine di quel dominio scelto.
(3) In tutte le pagine https://www.example.com (l' altro dominio), utilizzare javascript per impostare document.domain = "example.com";
. Quindi crea anche un nascosto <iframe>
e navigalo in una pagina sul dominio https://example.com scelto ( non importa quale , purché tu possa inserire un piccolo frammento di javascript lì. Se tu " stai creando il sito, crea una pagina vuota appositamente per questo scopo. Se stai scrivendo un'estensione o uno script utente in stile Greasemonkey e quindi non hai alcun controllo sulle pagine su example.com server della pagina , scegli la pagina più leggera che puoi trovare e inserisci il tuo script in essa. Alcuni tipo di pagina "non trovata" probabilmente andrebbe bene).
(4) Lo script sulla pagina iframe nascosto deve solo (a) essere impostato document.domain = "example.com";
e (b) notificare alla finestra genitore quando ciò è fatto. Dopodiché, la finestra genitore può accedere alla finestra iframe e a tutti i suoi oggetti senza restrizioni! Quindi la pagina iframe minimo è qualcosa del tipo:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
Se scrivi uno script utente, potresti non voler aggiungere funzioni accessibili esternamente come iframeReady()
al tuo unsafeWindow
, quindi invece un modo migliore per notificare lo script utente della finestra principale potrebbe essere quello di utilizzare un evento personalizzato:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Che rileveresti aggiungendo un listener per l'evento "iframeReady" personalizzato alla finestra della tua pagina principale.
(NOTA: devi impostare document.domain = "esempio.com" anche se il dominio dell'iframe è già esempio.com : l'assegnazione di un valore a document.domain imposta implicitamente la porta di origine su null ed entrambe le porte devono corrispondere per l'iframe e il suo genitore devono essere considerati della stessa origine. Vedere la nota qui: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin )
(5) Una volta che il nascosti iframe ha informato la sua finestra di padre che è pronto, lo script nella finestra genitore può semplicemente utilizzare iframe.contentWindow.localStorage
, iframe.contentWindow.indexedDB
, iframe.contentWindow.BroadcastChannel
, iframe.contentWindow.SharedWorker
invece di window.localStorage
, window.indexedDB
ecc ... e tutti questi oggetti saranno scope alla scelta https: // example.com origin, quindi avranno la stessa origine condivisa per tutte le tue pagine!
La parte più imbarazzante di questa tecnica è che devi attendere il caricamento dell'iframe prima di procedere. Quindi non puoi semplicemente iniziare a usare allegramente localStorage nel tuo gestore DOMContentLoaded, per esempio. Inoltre potresti voler aggiungere un po 'di gestione degli errori per rilevare se l'iframe nascosto non riesce a caricarsi correttamente.
Ovviamente, dovresti anche assicurarti che l'iframe nascosto non venga rimosso o navigato durante la vita della tua pagina ... OTOH Non so quale sarebbe il risultato, ma molto probabilmente potrebbero accadere cose brutte.
E un avvertimento: l'impostazione / modifica document.domain
può essere bloccata utilizzando l' Feature-Policy
intestazione, nel qual caso questa tecnica non sarà utilizzabile come descritto.
Tuttavia, c'è una generalizzazione significativamente più complicata di questa tecnica, che non può essere bloccata da Feature-Policy
, e che consente anche a domini completamente non correlati di condividere dati, comunicazioni e lavoratori condivisi (cioè non solo sottodomini di un comune superdominio). @Mayank Jain lo ha già descritto nella loro risposta, ovvero:
L'idea generale è che, proprio come sopra, crei un iframe nascosto per fornire l'origine corretta per l'accesso; ma invece di afferrare direttamente le proprietà della finestra dell'iframe, usi lo script all'interno dell'iframe per fare tutto il lavoro e comunichi tra l'iframe e la tua finestra principale usando solo postMessage()
e addEventListener("message",...)
.
Funziona perché postMessage()
può essere utilizzato anche tra finestre di origine diversa. Ma è anche molto più complicato perché devi passare tutto attraverso una sorta di infrastruttura di messaggistica che crei tra l'iframe e la finestra principale, piuttosto che usare solo le API localStorage, IndexedDB, ecc. Direttamente nel codice della tua finestra principale.