Использовать localStorage для разных поддоменов

Я заменяю куки на localStorage в браузерах, которые могут их поддерживать (любой, кроме IE). Проблема заключается в site.com и www. site.com хранит свои отдельные объекты localStorage. Я считаю, что www считается поддоменом (глупое решение, если вы спросите меня). Если пользователь изначально был на site.com и решил ввести www. site.com во время ее следующего посещения, все ее личные данные будут недоступны. Как я могу получить все мои "субдомены" для совместного использования в том же localStorage, что и основной домен?

6 ответов

Решение

Вот как я использую его в разных доменах...

  • Используйте iframe из вашего родительского домена - скажем parent.com
  • Затем на каждом домене child.com просто выполните postMessage для своего iframe parent.com.
  • Все, что вам нужно сделать, - это настроить протокол интерпретации ваших сообщений postMessage для общения с iframe parent.com.

Я надеюсь, что это помогает:)

Если вы используете решение iframe и postMessage только для этой конкретной проблемы, я думаю, что может быть меньше работы (как с точки зрения кода, так и с точки зрения вычислений), чтобы просто сохранить данные в cookie без поддоменов и, если это еще не сделано в localStorage при загрузке, возьмите его из cookie.

Плюсы:

  • Не требует дополнительных настроек iframe и postMessage.

Минусы:

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

Я согласен с другими комментаторами, хотя, похоже, это должен быть настраиваемый параметр для localStorage, поэтому обходные пути не требуются.

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

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

Установить cookie в основном домене -

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

а затем возьмите данные из любого основного домена или поддомена и установите их в localStorage

Вот как:

Для разделения доступа между поддоменами данного супердомена (например, 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 нужно только (а) установить document.domain = "example.com";, и (б) уведомить родительское окно, когда это будет сделано. После этого родительское окно может получить доступ к окну 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 неявно устанавливает для порта источника значение null, и оба порта должны совпадать для iframe. и его родительский элемент должен рассматриваться как тот же источник. См. примечание здесь: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)

(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 правильно.

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

И нюанс: установка / изменение document.domainможно заблокировать с помощьюFeature-Policy заголовок, и в этом случае этот метод нельзя будет использовать, как описано.


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

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

Это работает, потому что postMessage()может использоваться даже между окнами разного происхождения. Но это также значительно сложнее, потому что вам нужно передать все через какую-то инфраструктуру обмена сообщениями, которую вы создаете между iframe и главным окном, а не просто использовать API localStorage, IndexedDB и т. Д. Непосредственно в коде вашего главного окна.

Я использую xdLocalStorage, это легковесная библиотека js, которая реализует интерфейс LocalStorage и поддерживает междоменное хранение с помощью обмена сообщениями iframe после сообщения (поддержка angularJS).

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

Такое решение вызывает множество подобных проблем. по соображениям согласованности и SEO перенаправление на основной домен - лучшее решение.

сделать это перенаправление на уровне сервера

Как перенаправить www на не-www с помощью Nginx

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

или любой другой уровень, например маршрут 53, если вы используете

Вот как я решил это для моего сайта. Я перенаправил все страницы без www на www.site.com. Таким образом, это всегда займет местное хранилище www.site.com

Добавьте следующее в ваш .htacess(создайте его, если у вас его еще нет) в корневом каталоге

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

Вы можете просто использовать document.domain имущество. Если вы поместите это в первые действия JavaScript:

document.domain="mysite.com";
Другие вопросы по тегам