використовуйте localStorage для субдоменів


95

Я замінюю файли cookie на localStorage у браузерах, які можуть це підтримувати (будь-хто, крім IE). Проблема полягає у site.com та www . site.com зберігають власні окремі об’єкти localStorage. Я вважаю, що www вважається субдоменом (дурне рішення, якщо ви запитаєте мене). Якщо користувач спочатку був на сайті.com і вирішив ввести www . site.com під час її наступного відвідування, всі її персональні дані будуть недоступні. Як отримати так, щоб усі мої "субдомени" мали спільний доступ до localStorage як основного домену?


4
Firefox та IE8 підтримують зберігання постійних даних у вказаному користувачем домені. Наприклад, на FF, ви можете зробити globalStorage ['site.com'], і це буде можливо на www.site.com та site.com. Я досі не зрозумів, як це зробити у реалізації Chrome.
JoJo

9
Подумайте про те, щоб скористатися одним або останнім - переспрямуйте всіх користувачів, які відвідують, за допомогою www. субдомен до домену без субдомену, або навпаки.
Елад Нава,

Я давно створив статтю: Міждоменне
місцеве зберігання

Відповіді:


94

Ось як я використовую його в різних доменах ...

  • Використовуйте iframe з батьківського домену - скажімо, parent.com
  • Тоді на кожному домені child.com просто зробіть postMessage до вашого батьківського iframe
  • Все, що вам потрібно зробити, це налаштувати протокол того, як інтерпретувати ваші повідомлення postMessage, щоб розмовляти з iframe-файлом parent.com.

Сподіваюся, це допоможе :)


2
Це справжня відповідь, а не відмічена. Я зробив це сам, але також створив зручну обгортку зворотного виклику з postMessage.
Джейсон Себрінг,

4
Ось хороша стаття з прикладом коду, що пояснює цей метод: jcubic.wordpress.com/2014/06/20/cross-domain-localstorage
Тодд Прайс

4
Зверніть увагу, що це можливо лише тоді, коли сторонні файли cookie не вимкнені: stackoverflow.com/a/44097269/4311428
Макс

6
Apple оновила за замовчуванням Safari 7+ як на настільному ПК, так і на мобільному телефоні, щоб заблокувати сторонні дані. Зараз опція називається "Блокувати файли cookie та інші дані веб-сайту", що стосується таких речей, як localstorage, які зараз повністю ізольовані доменом. Цей метод не працює в Safari
Aranganathan

2
@Max @Aranganathan, він все ще працює для оригінального випадку запитання - site.com/ www.site.comпоки субдомени знаходяться в одному батьківському домені
Костянтин

40

Якщо ви використовуєте рішення iframe та postMessage саме для цієї конкретної проблеми, я вважаю, що може бути менше праці (як кодової, так і обчислювальної), щоб просто зберігати дані у файлі cookie без субдомену, і якщо це ще не зроблено у localStorage при завантаженні, візьміть його з файлу cookie .

Плюси:

  • Не потребує налаштування додаткового iframe та postMessage.

Мінуси:

  • Зробить дані доступними для всіх субдоменів (не лише для www), тому, якщо ви не довіряєте всім субдоменам, це може не працювати для вас.
  • Буде надсилати дані на сервер при кожному запиті. Не чудово, але залежно від вашого сценарію, можливо, все-таки менше роботи, ніж рішення iframe / postMessage.
  • Якщо ви робите це, чому б просто не використовувати файли cookie безпосередньо? Залежить від вашого контексту.
  • Максимальний розмір файлу cookie 4K, загальний для всіх файлів cookie для домену (Дякую Блейку за те, що він вказав на це в коментарях)

Я погоджуюсь з іншими коментаторами, однак, схоже, це має бути специфічним варіантом для localStorage, тому обхідні роботи не потрібні.


29
Con: 4k максимальний розмір файлів cookie
Блейк Міллер,

17
Крім того, як я дізнався з важкого шляху, обмеження 4 кб стосується суми розмірів усіх файлів cookie для одного домену, а не для кожного файлу cookie.
Blake Miller

інші мінуси: - файли cookie, швидше за все, будуть заблоковані блокувальниками реклами - файли cookie призначені для обміну невеликими даними між сервером і клієнтом; якщо сервер не використовує дані, які ви зберігаєте в файлі cookie, це, як наслідок, неправильне використання
Enno

32

Я пропоную зробити сайт.com переспрямовуванням на www.site.com як для узгодженості, так і для уникнення таких проблем.

Також розгляньте можливість використання крос-браузерного рішення, такого як PersistJS, яке може використовувати власне сховище кожного браузера.


У мене немає доступу адміністратора до серверів для здійснення такого перенаправлення. Чи дозволяє ця бібліотека ділитися постійними даними між www і не www? Почитавши, здається, що майже всі механізми зберігання браузерів цього не дозволяють. Незалежно від того, це файли cookie або localStorage, ми зіткнемося з цією проблемою ...
JoJo

Так, зберігання зазвичай залежить від домену, включаючи субдомен. Ось чому я запропонував переспрямування. Вам не обов'язково потрібен доступ адміністратора, просто використовуйте правило .htaccess у корені документа
Eran Galperin

1
@JoJo Є кілька способів переспрямування, наприклад, надіславши заголовок Location, або через <meta>тег HTML, або навіть JS через window.location.
Sony Santos,

1
Це просто уникає відповіді. Відповідь Маянка дивіться як правильну.
Джейсон Себрінг,

1
+1 @ уникнення, плюс це не має значення для інших випадків - наприклад, для того, для якого я тут lang1.domain.com - lang2.domain.com
r --------- k

6

Встановити як файл cookie в основному домені -

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

а потім взяти дані з будь-якого основного домену або піддомену та встановити їх на localStorage


4

Я використовую xdLocalStorage, це полегшена js-бібліотека, яка реалізує інтерфейс LocalStorage та підтримує міждоменне зберігання за допомогою зв'язку після повідомлення iframe. (Підтримка angularJS)

https://github.com/ofirdagan/cross-domain-local-storage


3
Я подивився, але схоже, це не працює в Safari. github.com/ofirdagan/cross-domain-local-storage/issues/10
Андріс Залітіс

1

подібне рішення викликає багато подібних проблем. для узгодженості та міркувань щодо SEO перенаправлення на основний домен є найкращим рішенням.

зробити це переспрямування на рівні сервера

Як перенаправити www на не-www за допомогою Nginx

https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-centos-7

або будь-який інший рівень, такий як маршрут 53, якщо ви використовуєте


1

Ось як:

Для спільного використання між субдоменами даного супердомену (наприклад, example.com) існує техніка, яку ви можете використовувати у цій ситуації. Він може бути застосований до localStorage, IndexedDB, SharedWorker, BroadcastChannelі т.д., всі з яких мають загальну функціональність між ж походження сторінок, але з якоїсь - то причини не дотримуються будь - яких змін вdocument.domain які дозволили б їм використовувати супербудинку як їх походження безпосередньо.

(1) Виберіть один «основний» домен, до якого належать дані: тобто https://example.com або https://www.example.com зберігатимуть ваші дані localStorage. Скажімо, ви вибрали https://example.com .

(2) Використовуйте localStorage зазвичай для сторінок вибраного домену.

(3) На всіх https://www.example.com сторінках ( інший домен) використовуйте javascript для встановлення document.domain = "example.com";. Потім також створіть приховану <iframe>та перейдіть до якоїсь сторінки у вибраному домені https://example.com ( Не має значення, на якій сторінці , якщо ви можете туди вставити дуже маленький фрагмент javascript. Якщо ви створюючи веб-сайт, просто створіть порожню сторінку спеціально для цього. Якщо ви пишете розширення або користувацький скрипт у стилі Greasemonkey і тому не маєте контролю над сторінками на example.comпросто виберіть найлегшу сторінку, яку ви можете знайти, і вставте в неї свій сценарій. Якась сторінка "не знайдено", мабуть, буде в порядку).

(4) Сценарій на прихованій сторінці iframe повинен мати лише (a) набір document.domain = "example.com";і (b) повідомляти батьківське вікно, коли це буде зроблено. Після цього батьківське вікно може отримати доступ до вікна iframe та всіх його об’єктів без обмежень! Тож мінімальна сторінка iframe - це щось на зразок:

<!doctype html>
<html>
<head>
  <script>
    document.domain = "example.com";
    window.parent.iframeReady();  // function defined & called on parent window
  </script>
</head>
<body></body>
</html>

Якщо ви пишете скрипт користувача, ви, можливо, не захочете додавати зовнішні функції, такі як iframeReady()до вашого unsafeWindow, тому натомість кращим способом сповіщення головного вікна може бути використання користувацької події:

    window.parent.dispatchEvent(new CustomEvent("iframeReady"));

Що ви виявили б, додавши прослуховувач спеціальної події "iframeReady" у вікно головної сторінки.

(ПРИМІТКА. Вам потрібно встановити document.domain = "example.com", навіть якщо домен iframe вже є example.com : Присвоєння значення document.domain неявно встановлює нульовий порт походження , і обидва порти повинні збігатися для iframe та його батьківщину вважати однаковим. Дивіться примітку тут: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin )

(5) Після того , як прихований IFrame повідомив його батьківське вікно , що він готовий, сценарій в батьківському вікні можна просто використовувати iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorkerа window.localStorage, window.indexedDBі т.д. ... і всі ці об'єкти будуть область видимості обраної https: // example.com - тому вони матимуть те саме спільне джерело для всіх ваших сторінок!

Найбільш незручна частина цієї техніки полягає в тому, що перед тим, як продовжувати, вам доведеться дочекатися завантаження iframe. Отже, ви не можете просто легко розпочати використання localStorage у своєму обробнику DOMContentLoaded, наприклад. Також, можливо, ви захочете додати деяку обробку помилок, щоб виявити, чи не вдається завантажити приховану рамку.

Очевидно, вам слід також переконатись, що прихований iframe не видаляється та не переміщується протягом усього періоду вашої сторінки ... OTOH, я не знаю, яким буде результат, але дуже ймовірно, що трапляться погані речі.

І, застереження: налаштування / зміна document.domainможе бути заблокована за допомогою Feature-Policyзаголовка, і в цьому випадку ця техніка не буде застосована, як описано.


Однак існує значно більш складне узагальнення цієї методики, яке неможливо заблокувати Feature-Policy, а це також дозволяє абсолютно не пов’язаним доменам обмінюватися даними, зв’язками та спільними працівниками (тобто не просто субдоменами загального наддомену). @Mayank Jain це вже описав у своїй відповіді, а саме:

Загальна ідея полягає в тому, що, як і вище, ви створюєте прихований iframe для забезпечення правильного джерела доступу; але замість того, щоб просто захоплювати властивості вікна iframe безпосередньо, ви використовуєте сценарій всередині iframe, щоб виконати всю роботу, і ви спілкуєтесь між iframe та вашим головним вікном лише за допомогою postMessage()та addEventListener("message",...).

Це працює, оскільки postMessage()його можна використовувати навіть між вікнами різного походження. Але це також значно складніше, тому що ви повинні передавати все через якусь інфраструктуру обміну повідомленнями, яку ви створюєте між iframe та головним вікном, а не просто використовуючи API localStorage, IndexedDB тощо. Безпосередньо в коді вашого головного вікна.


0

Ось як я це вирішив для свого веб-сайту. Я перенаправив усі сторінки без www на www.site.com. Таким чином, завжди буде потрібно місцеве зберігання www.site.com

Додайте в свій .htacess наступне (створіть його, якщо у вас його ще немає) у кореневій директорії

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

5
Мені дуже спокушається проголосувати проти цього, але я не буду, бо це може допомогти застосуванню OP, але для людей, які хочуть вести сеанси через myapp.com та developers.myapp.com та support.myapp.com, ця відповідь: не добре.
Дон Омонді,

привіт @DonOmondi Буду вдячний, якщо ви допоможете мені з посиланнями на те, що ви пропонуєте!
Аюш Бахеті

3
ОП запитало "використовувати localStorage між субдоменами". Ваша відповідь - "перенаправити www на не-www" дуже різні речі, але це може працювати тоді і лише тоді, коли конкретний субдомен "www.abc.com", для загальних випадків наведені інші відповіді тут більш практичний.
Дон Омонді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.