Ответ 1
Хорошо, пройдя много разных итераций, вот реализация, с которой мы закончили:
Переменные
- Существует два типа хранилищ данных:
- IndexedDB, который используется для всех вкладок.
- sessionStorage, который уникален для каждой вкладки.
- Сохраняем следующие переменные:
- IndexedDB содержит
publicToken
,nextTabId
. - sessionStorage содержит
privateToken
,tabId
.
- IndexedDB содержит
publicToken, privateToken
- Для определения токена аутентификации см. fooobar.com/info/19466/....
- Существует два типа токенов аутентификации: открытый и закрытый.
-
publicToken
- это токен, возвращаемый последней операцией входа во все вкладки. -
privateToken
- это токен, возвращаемый последней операцией входа в текущую вкладку.
табетический
- Каждая вкладка уникально идентифицируется токеном под названием
tabId
. -
nextTabId
- это число, доступное для всех вкладок. - Если вкладка не имеет идентификатора, она создает новую на основе
nextTabId
и увеличивает ее значение. - Например,
tabId
может иметь значение "com.company.TabX
", где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
и обратно на исходную страницу).
Извините за подробные детали реализации, но я не смог найти более легкое/более короткое решение.