gunakan localStorage di seluruh subdomain

101

Saya mengganti cookie dengan localStorage di browser yang dapat mendukungnya (siapa pun kecuali IE). Masalahnya adalah site.com dan www . site.com menyimpan objek localStorage mereka sendiri yang terpisah. Saya yakin www dianggap sebagai subdomain (keputusan bodoh jika Anda bertanya kepada saya). Jika pengguna awalnya di site.com dan memutuskan untuk mengetik www . site.com pada kunjungan berikutnya, semua data pribadinya tidak dapat diakses. Bagaimana cara agar semua "subdomain" saya berbagi penyimpanan lokal yang sama dengan domain utama?

JoJo
sumber
4
Firefox dan IE8 mendukung penyimpanan data persisten di bawah domain yang ditentukan pengguna. Misalnya di FF, Anda dapat melakukan globalStorage ['site.com'] dan ini dapat diakses di www.site.com dan site.com. Saya masih belum menemukan cara melakukan ini dalam penerapan Chrome.
JoJo
9
Pertimbangkan untuk menggunakan salah satu atau yang terakhir - arahkan ulang semua pengguna yang mengunjungi dengan www. subdomain ke domain tanpa subdomain, atau sebaliknya.
Elad Nava
1
Saya sudah lama membuat artikel: Cross-Domain LocalStorage
jcubic

Jawaban:

97

Beginilah cara saya menggunakannya di seluruh domain ...

  • Gunakan iframe dari domain induk Anda - katakanlah parent.com
  • Kemudian di setiap domain child.com, cukup lakukan postMessage ke iframe induk.com Anda
  • Yang perlu Anda lakukan adalah menyiapkan protokol tentang cara menafsirkan pesan postMessage Anda untuk berbicara dengan iframe parent.com.

Saya harap ini membantu :)

Mayank Jain
sumber
2
Ini adalah jawaban yang sebenarnya, bukan jawaban yang dicentang. Saya telah melakukan ini sendiri tetapi juga membuat pembungkus panggilan balik yang nyaman dengan postMessage.
Jason Sebring
4
Berikut adalah artikel bagus dengan beberapa contoh kode yang menjelaskan metode ini: jcubic.wordpress.com/2014/06/20/cross-domain-localstorage
Harga Todd
4
Perhatikan bahwa ini hanya mungkin jika cookie pihak ketiga tidak dinonaktifkan: stackoverflow.com/a/44097269/4311428
maxeh
6
Apple telah memperbarui default di Safari 7+ baik di desktop dan seluler untuk memblokir data pihak ketiga. Opsi tersebut sekarang disebut "Blokir cookie dan data situs web lainnya" yang merujuk pada hal-hal seperti penyimpanan lokal yang sekarang sepenuhnya diisolasi oleh domain. Metode ini tidak akan berfungsi di Safari
Aranganathan
2
@Max @Aranganathan itu masih berfungsi untuk kasus pertanyaan asli - site.com/ www.site.comselama subdomain berada di domain induk yang sama
Kostiantyn
42

Jika Anda menggunakan solusi iframe dan postMessage hanya untuk masalah khusus ini, menurut saya mungkin akan kurang berhasil (baik dari segi kode maupun komputasi) untuk hanya menyimpan data dalam cookie tanpa subdomain dan, jika belum di localStorage saat dimuat, ambil dari cookie .

Kelebihan:

  • Tidak memerlukan iframe tambahan dan pengaturan postMessage.

Kekurangan:

  • Akan membuat data tersedia di semua subdomain (bukan hanya www) jadi jika Anda tidak mempercayai semua subdomain itu mungkin tidak berfungsi untuk Anda.
  • Akan mengirimkan data ke server pada setiap permintaan. Tidak bagus, tetapi tergantung pada skenario Anda, mungkin masih kurang berfungsi daripada solusi iframe / postMessage.
  • Jika Anda melakukan ini, mengapa tidak menggunakan cookie secara langsung? Tergantung pada konteks Anda.
  • Ukuran cookie maksimal 4K, total di semua cookie untuk domain (Terima kasih kepada Blake karena menunjukkan hal ini di komentar)

Saya setuju dengan pemberi komentar lain, sepertinya ini harus menjadi opsi yang dapat ditentukan untuk Penyimpanan lokal sehingga penyelesaian tidak diperlukan.

Matt
sumber
32
Kontra: Ukuran cookie maksimum 4k
Blake Miller
18
Selain itu, saat saya belajar dari pengalaman yang sulit, batas 4k adalah untuk jumlah ukuran semua cookie untuk satu domain, bukan untuk setiap cookie.
Blake Miller
kontra lainnya: - cookie kemungkinan besar akan diblokir oleh adblocker - cookie dimaksudkan untuk digunakan untuk berbagi data kecil antara server dan klien, jika server tidak menggunakan data yang Anda simpan dalam cookie, akibatnya ini adalah penyalahgunaan
Enno
33

Saya sarankan membuat pengalihan site.com ke www.site.com untuk konsistensi dan menghindari masalah seperti ini.

Selain itu, pertimbangkan untuk menggunakan solusi lintas-browser seperti PersistJS yang dapat menggunakan penyimpanan asli setiap browser.

Eran Galperin
sumber
Saya tidak memiliki akses admin ke server untuk melakukan pengalihan seperti itu. Apakah perpustakaan itu memungkinkan saya untuk berbagi data persisten antara www dan non-www? Setelah melakukan beberapa pembacaan, sepertinya hampir semua mekanisme penyimpanan browser tidak mengizinkannya. Tidak peduli apakah itu cookie atau localStorage, kita akan mengalami masalah ini ...
JoJo
Ya, penyimpanan biasanya bergantung pada domain, termasuk subdomain. Inilah mengapa saya menyarankan pengalihan. Anda tidak perlu akses admin, cukup gunakan aturan .htaccess di root dokumen
Eran Galperin
1
@JoJo Ada beberapa cara untuk redirect, misalnya dengan mengirimkan header Location, atau melalui <meta>tag HTML, atau bahkan melalui JS window.location.
Sony Santos
1
Ini hanya menghindari jawabannya. Lihat jawaban Mayank sebagai benar.
Jason Sebring
1
+1 @menghindari, ditambah lagi ini tidak relevan untuk kasus lain - seperti kasus saya di sini lang1.domain.com - lang2.domain.com
r --------- k
11

Setel ke cookie di domain utama -

document.cookie = "key=value;domain=.mydomain.com"

dan kemudian mengambil data dari domain utama atau sub domain dan mengaturnya di penyimpanan lokal

URL87
sumber
2

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.domainyang 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();  // function defined & called on parent window
  </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.SharedWorkerbukan 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.domaindapat diblokir menggunakan Feature-Policyheader, 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.

Doin
sumber
0

Beginilah cara saya menyelesaikannya untuk situs web saya. Saya mengarahkan ulang semua halaman tanpa www ke www.site.com. Dengan cara ini, ini akan selalu mengambil penyimpanan lokal dari www.site.com

Tambahkan berikut ini ke .htacess Anda , (buat satu jika Anda belum memilikinya) di direktori root

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
Ayush Baheti
sumber
6
Saya sangat tergoda untuk mengecilkan ini tetapi saya tidak akan melakukannya karena dapat membantu kasus penggunaan OP, tetapi untuk orang yang ingin menyimpan sesi di myapp.com dan developers.myapp.com dan support.myapp.com, jawaban ini adalah tidak baik.
Don Omondi
hai @DonOmondi Saya akan sangat menghargai jika Anda dapat membantu saya dengan tautan untuk apa yang Anda sarankan!
Ayush Baheti
3
OP bertanya "gunakan penyimpanan lokal di seluruh subdomain" jawaban Anda adalah "mengalihkan www ke non-www" hal-hal yang sangat berbeda tetapi dapat bekerja jika dan hanya jika subdomain spesifiknya adalah "www.abc.com" untuk kasus umum beberapa jawaban lain di sini adalah lebih praktis.
Don Omondi