Связывание данных, привязанных к табу, к запросу HTTP GET

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

Вот правила этой системы:

  • Маркер аутентификации указывает, какой пользователь зарегистрирован.
  • Есть два типа токенов аутентификации: частные и общедоступные.
  • Каждый закрытый токен привязан к одной вкладке и определяет ее учетную информацию.
  • Открытый токен может быть прочитан/записан любой вкладкой и отображен на последней учетной записи, которая была зарегистрирована (на всех вкладках).
  • Когда пользователь выходит на любую вкладку, удаляются как личные, так и общедоступные токены.
  • Каждый раз, когда вкладка попадает на страницу, требующую аутентификации, система пытается прочитать частный токен. Если он не установлен (как в случае новой/пустой вкладки), он пытается копировать значение общедоступного токена в закрытый токен. Если общедоступный токен не установлен, пользователь перенаправляется на экран проверки подлинности.
  • Когда вкладка уже зарегистрирована и пользователь нажимает на ссылку, запрос должен содержать закрытый токен в пользовательском HTTP-заголовке. Отправка этой информации в URI не является вариантом по соображениям безопасности.
  • Возможность навигации с помощью кнопки "назад/вперед" так же, как и для обычных ссылок (что означает, никаких приглашений для повторной отправки данных формы).

Что я пробовал до сих пор:

  • Использование cookies для личных и общедоступных токенов: это не работает, потому что сервер не знает, какой куки файл должен выглядеть. Если пользователь нажимает на ссылку из вкладки, запрос отправляет все файлы cookie на всех вкладках, и сервер не знает, какой из них щелкнул по ссылке.

  • Сохранение личных токенов в sessionStorage: это не работает, потому что когда пользователь нажимает на ссылку, нет способа указать пользовательские заголовки, которые должны отправляться вместе с запросом HTTP GET.

  • Запрос страницы с помощью AJAX, а затем переход на страницу в памяти с использованием URI данных: по соображениям безопасности Internet Explorer не разрешает использование URI UATA для содержимого HTML. См. http://msdn.microsoft.com/en-us/library/cc848897%28v=vs.85%29.aspx

  • Использование <form method="get" enctype="multipart/form-data"> и передача токена с помощью скрытых полей: enctype = "multipart/form-data" поддерживается только для POST.

  • Использование <form method="post" enctype="multipart/form-data"> и передача маркера с помощью скрытых полей: теоретически это должно работать, но теперь пользователю будет предложено повторно отправить данные формы, если он использует кнопку "назад/вперед".

  • Запрос страницы с помощью AJAX, а затем переписывание текущей страницы с помощью document.open(); document.write(); document.close(). Я пробовал как qaru.site/info/19688/..., так и http://forums.mozillazine.org/viewtopic.php?p=5767285&sid=d6a5a2e8e311598cdbad124e277e0f52#p5767285 и в обоих случаях скрипты в новом блоке <head> никогда не будет выполняться.

Любые идеи?

Ответ 1

Хорошо, пройдя много разных итераций, вот реализация, с которой мы закончили:

Переменные

  • Существует два типа хранилищ данных:
    • IndexedDB, который используется для всех вкладок.
    • sessionStorage, который уникален для каждой вкладки.
  • Сохраняем следующие переменные:
    • IndexedDB содержит publicToken, nextTabId.
    • sessionStorage содержит privateToken, tabId.

publicToken, privateToken

  • Для определения токена аутентификации см. fooobar.com/info/19466/....
  • Существует два типа токенов аутентификации: открытый и закрытый.
  • publicToken - это токен, возвращаемый последней операцией входа во все вкладки.
  • privateToken - это токен, возвращаемый последней операцией входа в текущую вкладку.

табетический

  • Каждая вкладка уникально идентифицируется токеном под названием tabId.
  • nextTabId - это число, доступное для всех вкладок.
  • Если вкладка не имеет идентификатора, она создает новую на основе nextTabId и увеличивает ее значение.
  • Например, tabId может иметь значение "com.company.Tab X", где X - номер, возвращаемый nextTabId.

Войти/Выход

  • Каждый раз, когда вкладка регистрируется, privateToken и publicToken перезаписываются с использованием маркера аутентификации, возвращаемого сервером.
  • Когда пользователь выходит из системы, мы удаляем privateToken и publicToken со стороны браузера и privateToken на стороне сервера. Мы не удаляем publicToken на стороне сервера.
  • Это означает, что в любое время, когда вы выберете вкладку, все вкладки, имеющие один и тот же privateToken, также будут выходить из системы. Любые вкладки с использованием другого токена не будут затронуты.
  • Когда несколько вкладок имеют один и тот же privateToken? Когда вы открываете ссылку в новом окне или вкладке, она наследует privateToken родительской вкладки.
  • Если бы мы удалили publicToken на сервере, вкладка, состоящая из privateToken X, publicToken Y, вызовет вкладки с privateToken Y, чтобы выйти из системы (что нежелательно).

Загрузка страницы

  • Просмотрите страницу для ссылок HTML.
  • Для каждой ссылки добавьте параметр запроса tabId к URL-адресу. Значение параметра равно значению tabId.
  • Разделите параметр URL tabId на текущей странице с помощью history.replaceState(), чтобы пользователи могли обмениваться ссылками со своими друзьями (tabId зависит от пользователя и не может быть общим).
  • Удалить cookie tabId (подробнее об этом ниже).

При нажатии ссылки

  • На вкладке создается файл cookie tabId и следует по ссылке.
  • Файл cookie имеет имя, равное значению tabId, и значение, равное значению privateToken

Когда сервер получает запрос

  • Если параметр tabId отсутствует, переадресуйте браузер на GetTabId.html?referer=X, где X - текущий URL-адрес.
  • Если присутствует tabId, но токен аутентификации недействителен или истек, перенаправляйте браузер на экран входа в систему.

GetTabId.html

  • Если вкладка не имеет privateToken, скопируйте publicToken в privateToken.
  • Если оба privateToken и publicToken являются undefined, перенаправляйтесь на страницу входа.
  • На странице представлен URL-адрес с именем referer, который указывает, где перенаправить на успех.
  • Если вкладка имеет privateToken, добавьте параметр tabId на страницу referer и перенаправите ее обратно.
  • Используйте window.location.replace() при перенаправлении для удаления GetTabId.html из истории браузера.

Почему мы продолжаем удалять/добавлять файлы cookie?

  • Мы стараемся минимизировать количество файлов cookie, отправленных на сервер по каждому запросу.
  • Если мы не удалили cookie tabId cookie при загрузке страницы, то каждый раз, когда вкладка будет делать запрос, все остальные куки файлы будут также отправлены.

Известные проблемы

  • "Просмотр источника" открывает URL-адрес, отсутствующий tabId. В результате он получает исходный код страницы, который перенаправляет на GetTabId.html вместо фактической страницы.
  • Повторно загружается длинная страница (клиент перенаправляется на GetTabId.html и обратно на исходную страницу).

Извините за подробные детали реализации, но я не смог найти более легкое/более короткое решение.