0

Кросс-доменный доступ к LocalStorage с помощью JavaScript

49

Описание проблемы

У нас есть файл api.js, который находится на домене api.abc.com и управляет локальным хранилищем (local storage).

Мы подключили этот JavaScript-файл на наши сайты abc.com и login.abc.com через кросс-доменное подключение, используя следующий код:

<script src="http://api.abc.com/api.js"></script>

Я понимаю, что локальное хранилище привязано к каждому домену отдельно. Однако, поскольку api.js загружается с api.abc.com, я ожидал, что он сможет получить доступ к локальному хранилищу на api.abc.com с обоих доменов. К сожалению, это, похоже, не так. Когда api.js сохраняет значение в локальном хранилище с одного домена, оно недоступно, когда загружается с другого домена.

Есть ли какие-то идеи, почему это происходит и как можно решить эту проблему?

3 ответ(ов)

0

Чтобы использовать postMessage для междоменной передачи данных, можно организовать взаимодействие между вашим "неправильным" доменом и iframe, размещенным на "правильном" домене. В таком случае iframe будет отвечать за отправку сообщений, содержащих данные о куках, обратно на ваш основной веб-сайт.

Вот как это можно сделать:

  1. На странице "неправильного" домена вы вставляете iframe, который будет отправлять сообщения с куками.

  2. Пример кода для отправки сообщения через postMessage:

window.onload = function() {
    // Получаем окно, отображаемое в iframe.
    var receiver = document.getElementById('receiver').contentWindow;
    
    // Получаем ссылку на кнопку 'Отправить сообщение'.
    var btn = document.getElementById('send');

    // Функция для обработки отправки сообщения.
    function sendMessage(e) {
        // Предотвращаем поведение браузера по умолчанию.
        e.preventDefault();

        // Отправляем сообщение с текстом 'cookie data!' на новый домен.
        receiver.postMessage('cookie data!', 'http://wrong-domain.com');
    }

    // Добавляем обработчик событий, который будет вызывать функцию sendMessage()
    // при нажатии кнопки отправки.
    btn.addEventListener('click', sendMessage);
}
  1. Код для приема сообщения на "правильном" домене:
window.onload = function() {
    var messageEle = document.getElementById('message');
    
    function receiveMessage(e) {
        if (e.origin !== "http://correct-domain.com") return; // Проверка источника сообщения
        messageEle.innerHTML = "Сообщение получено: " + e.data; // Отображаем полученное сообщение
    }
    
    window.addEventListener('message', receiveMessage);
}

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

Для более детального изучения данной технологии, вот хороший источник: Cross-Domain Messaging with postMessage.

И вот пример в действии: CodePen Live Example.

0

Другие ответы игнорируют тот факт, что вы на самом деле не работаете с кросс-доменным доступом, а просто между поддоменами.

Вам все равно потребуется скрытый iframe, чтобы инкапсулировать источник хранилища localStorage, к которому вы хотите получить доступ (api.abc.com). Однако, установив document.domain = "abc.com" как в основном окне, так и в скрытом iframe, вы сможете взаимодействовать напрямую. (Обратите внимание, что этот подход устарел, может иметь проблемы с безопасностью и, по крайней мере, в Chrome требует отправки заголовка Origin-Agent-Cluster: ?0).

После этого вы можете просто использовать hiddenIFrame.contentWindow.localStorage вместо window.localStorage и забыть о проблемах, связанных с использованием postMessage().

Я опубликовал более детальную версию этого ответа здесь: https://stackoverflow.com/a/63602446/999120

0

Вы можете использовать iframe для хранения данных в локальном хранилище и API postMessage для общения между родительским доменом и iframe. Вот пошаговое руководство:

  1. Создайте iframe с обработчиком события сообщения для хранения данных в локальном хранилище домена iframe:

    window.addEventListener("message", handleMessage, false);
    
    function handleMessage(e) {
        let { key, value, method } = e.data;
        if (method == 'store') {
            window.localStorage.setItem(key, value); // Сохранение данных в локальном хранилище домена `iframe`
        } else if (method == 'retrieve') {
            let response = window.localStorage.getItem(key);
            e.source.postMessage({
                key,
                response,
                method: 'response'
            }, '*'); // Получение данных из локального хранилища
        }
    }
    
  2. Отправьте сообщение из родительского домена в iframe для хранения данных:

    document.getElementById('myFrameId').contentWindow.postMessage({
        key: 'key',
        value: data,
        method: 'store'
    });
    
  3. Получите данные из iframe:

    document.getElementById('myFrameId').contentWindow.postMessage({
        method: 'retrieve',
        key: 'key'
    });
    
    window.addEventListener("message", handleResponse, false);
    
    function handleResponse(e) {
        let { key, value, method } = e.data;
        if (method == 'response') {
            console.log('Response Key:', key);
            console.log('Response Value:', value);
        }
    }
    

Таким образом, вы можете организовать двустороннюю связь между родительским окном и iframe, сохраняя и извлекая данные из локального хранилища. Не забудьте убедиться, что домены iframe и родительского окна соответствуют политикам безопасности браузера, чтобы избежать проблем с кросс-доменным обменом сообщениями.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь