Begini caranya:
[ Pembaruan November 2020: Solusi ini bergantung pada kemampuan untuk mengatur document.domain
. Sayangnya, kemampuan untuk melakukan itu sekarang sudah ditinggalkan.]
Untuk berbagi antar subdomain dari superdomain tertentu (misalnya example.com), ada teknik yang dapat Anda gunakan dalam situasi itu. Hal ini dapat diterapkan untuk localStorage
, IndexedDB
, SharedWorker
, BroadcastChannel
, dll, semua yang menawarkan fungsionalitas dibagi antara halaman yang sama-asal, tapi untuk beberapa alasan tidak menghormati modifikasi apapun untuk document.domain
yang akan membiarkan mereka menggunakan superdomain sebagai asal-usul mereka langsung.
(1) Pilih satu domain "utama" untuk menyimpan data: yaitu https://example.com atau https://www.example.com akan menyimpan data localStorage Anda. Katakanlah Anda memilih https://example.com .
(2) Gunakan localStorage biasanya untuk halaman domain yang dipilih itu.
(3) Di semua halaman https://www.example.com ( domain lain ), gunakan javascript untuk menyetel document.domain = "example.com";
. Lalu buat juga yang tersembunyi <iframe>
, dan navigasikan ke beberapa halaman di domain https://example.com yang dipilih ( Tidak masalah halaman apa , selama Anda dapat memasukkan sedikit cuplikan javascript di sana. Jika Anda ' membuat ulang situs, cukup buat halaman kosong khusus untuk tujuan ini. Jika Anda menulis ekstensi atau skrip pengguna gaya Greasemonkey sehingga tidak memiliki kontrol apa pun atas halaman di example.comserver, cukup pilih halaman paling ringan yang dapat Anda temukan dan masukkan skrip Anda ke dalamnya. Beberapa jenis halaman "tidak ditemukan" mungkin akan baik-baik saja).
(4) Skrip di halaman iframe yang tersembunyi hanya perlu (a) set document.domain = "example.com";
, dan (b) memberi tahu jendela induk ketika ini selesai. Setelah itu, jendela induk dapat mengakses jendela iframe dan semua objeknya tanpa batasan! Jadi halaman iframe minimal adalah seperti:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady();
</script>
</head>
<body></body>
</html>
Jika menulis userscript, Anda mungkin tidak ingin menambahkan fungsi yang dapat diakses secara eksternal seperti iframeReady()
ke Anda unsafeWindow
, jadi cara yang lebih baik untuk memberi tahu jendela utama userscript adalah dengan menggunakan peristiwa khusus:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Yang akan Anda deteksi dengan menambahkan listener untuk peristiwa "iframeReady" kustom ke jendela halaman utama Anda.
(CATATAN: Anda perlu menyetel document.domain = "example.com" meskipun domain iframe sudah menjadi example.com : Menetapkan nilai ke document.domain secara implisit menyetel port asal ke null, dan kedua port harus cocok untuk iframe dan induknya dianggap sama-asal. Lihat catatan di sini: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin )
(5) Setelah disembunyikan iframe telah menginformasikan jendela induknya yang sudah siap, naskah di jendela orangtua bisa menggunakan iframe.contentWindow.localStorage
, iframe.contentWindow.indexedDB
, iframe.contentWindow.BroadcastChannel
, iframe.contentWindow.SharedWorker
bukan window.localStorage
, window.indexedDB
, dll ... dan semua benda-benda ini akan scoped untuk yang dipilih https: // example.com asal - jadi mereka akan memiliki asal bersama yang sama ini untuk semua halaman Anda!
Bagian paling canggung dari teknik ini adalah Anda harus menunggu iframe dimuat sebelum melanjutkan. Jadi Anda tidak bisa begitu saja mulai menggunakan localStorage di handler DOMContentLoaded Anda, misalnya. Anda juga mungkin ingin menambahkan beberapa penanganan kesalahan untuk mendeteksi jika iframe yang tersembunyi gagal dimuat dengan benar.
Tentunya, Anda juga harus memastikan iframe yang tersembunyi tidak dihapus atau dinavigasi selama masa aktif halaman Anda ... OTOH Saya tidak tahu apa akibatnya, tetapi kemungkinan besar hal-hal buruk akan terjadi.
Dan, peringatan: pengaturan / perubahan document.domain
dapat diblokir menggunakan Feature-Policy
header, dalam hal ini teknik ini tidak akan dapat digunakan seperti yang dijelaskan.
Namun, ada generalisasi yang jauh lebih rumit dari teknik ini, yang tidak dapat diblokir oleh Feature-Policy
, dan itu juga memungkinkan domain yang sama sekali tidak terkait untuk berbagi data, komunikasi, dan pekerja bersama (yaitu tidak hanya subdomain dari superdomain umum). @ Mayank Jain sudah memaparkannya dalam jawabannya, yaitu:
Ide umumnya adalah, seperti di atas, Anda membuat iframe tersembunyi untuk memberikan akses asal yang benar; tetapi alih-alih hanya mengambil properti jendela iframe secara langsung, Anda menggunakan skrip di dalam iframe untuk melakukan semua pekerjaan, dan Anda berkomunikasi antara iframe dan jendela utama Anda hanya menggunakan postMessage()
dan addEventListener("message",...)
.
Ini berfungsi karena postMessage()
dapat digunakan bahkan di antara jendela asal yang berbeda. Tetapi ini juga jauh lebih rumit karena Anda harus meneruskan semuanya melalui beberapa jenis infrastruktur perpesanan yang Anda buat antara iframe dan jendela utama, daripada hanya menggunakan localStorage, IndexedDB, dll. API langsung di kode jendela utama Anda.