Оригинал: https://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/

 

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

Обновление информации о соответствующем механизме хранения браузера.

  1. localStorage ~5 МБ, хранение без ограничения по времени, до тех пор, пока пользователь не удалит это вручную.
  2. sessionStorage ~5 МБ, хранение на всю жизнь текущей вкладки.
  3. cookie ~4 КБ, может быть сохранен до бесконечности.
  4. session cookie ~4 КБ, удаляется, когда пользователь закрывает браузер (не всегда удаляется).

Безопасное кэширование токенов сессии.

При работе с критическими платформами ожидается, что сеанс завершается, когда пользователь закрывает вкладку.
Чтобы поддержать это, никогда не следует использовать файлы cookie для хранения каких-либо конфиденциальных данных, таких как токены аутентификации. Даже сессионных файлов cookie будет недостаточно, так как они будут продолжать жить после закрытия вкладки и даже после полного закрытия браузера.
(В любом случае мы должны рассмотреть вопрос о том, чтобы не использовать файлы cookie, поскольку у них есть другие проблемы, которые необходимо решить, т. е. CSRF.)

Это оставляет нам возможность сохранить токен в памяти или в хранилище сеансов. Преимущество sessionStorage заключается в том, что он будет сохраняться на разных страницах и обновляться браузером. Таким образом, пользователь может перейти на другие страницы и/или обновить страницу и по-прежнему оставаться в системе.

Хорошо. Мы сохраняем токен в хранилище сеансов, отправляем его в виде заголовка с каждым запросом на сервер для аутентификации пользователя. Когда пользователь закрывает вкладку – она исчезает.

Но как насчет нескольких вкладок?

Довольно часто даже в одностраничном приложении пользователь захочет использовать несколько вкладок. Вышеупомянутая мера безопасности по сохранению токена в хранилище сеансов создаст некоторый плохой UX в виде запроса пользователя на повторный вход в систему с каждой открываемой им вкладкой. Правильно, sessionStorage не является общим для всех вкладок.

Общий доступ к хранилищу сеансов между вкладками с помощью событий localStorage.

Я решил эту проблему с помощью событий localStorage.
Когда пользователь открывает новую вкладку, мы сначала спрашиваем любую другую открытую вкладку, есть ли у него уже sessionStorage для нас. Если откроется какая-либо другая вкладка, она отправит нам sessionStorage через событие localStorage, мы продублируем его в sessionStorage.
Данные sessionStorage не останутся в локальном хранилище даже на 1 миллисекунду, поскольку они будут удалены в том же вызове. Данные передаются через полезную нагрузку события, а не через само локальное хранилище.

Демо здесь.

Нажмите кнопку “Set the sessionStorage”, а затем откройте несколько вкладок, чтобы увидеть, что хранилище сеансов является общим.

Почти идеально.

Теперь у нас есть, вероятно, самый безопасный способ кэширования токенов сеанса в браузере и без ущерба для работы с несколькими вкладками. Таким образом, когда пользователь закрывает вкладку, он точно знает, что сеанс закончился. Или это так?!

И Chrome, и Firefox оживят хранилище сеансов, когда пользователь выберет “Повторно открыть закрытую вкладку” и “Отменить закрытие вкладки” соответственно.
Черт возьми!

Safari делает это правильно и не восстанавливает sessionStorage (проверено только с этими 3 браузерами).

Для пользователя единственный способ быть полностью уверенным в том, что sessionStorage действительно исчез, - это открыть тот же веб-сайт напрямую и без функции “открыть закрытую вкладку”.
Это до тех пор, пока Chrome и Firefox не устранят эту ошибку. (моя интуиция подсказывает мне, что они назовут это “особенностью“).

Даже с этой ошибкой использование sessionStorage по-прежнему безопаснее, чем файл session-cookie или любая другая альтернатива. Если мы хотим сделать его идеальным, нам нужно будет реализовать тот же механизм, используя память вместо sessionStorage. (onbeforeunload и тому подобное тоже могут работать, но не будут такими надежными и будут очищаться также при обновлении. window.name почти хорошо , но он слишком стар и не имеет междоменной защиты).

Совместное использование хранилища памяти между вкладками для безопасной аутентификации с несколькими вкладками.

Так… это будет единственный реальный безопасный способ сохранить токен аутентификации в сеансе браузера и позволит пользователю открывать несколько вкладок без необходимости повторного входа в систему.

Закройте вкладку, и сеанс исчезнет – на этот раз по-настоящему.

Недостатком является то, что при наличии только одной вкладки обновление браузера заставит пользователя повторно войти в систему. Безопасность имеет свою цену, очевидно, что это не рекомендуется для любого типа систем.

Демо здесь.

Установите хранилище памяти memoryStorage и откройте несколько вкладок, чтобы оно было общим для них. Закройте все связанные вкладки, и маркер исчезнет навсегда (MemoryStorage - это просто объект javascript).

*
P.S.* Излишне говорить, что управление сеансами и истечение срока действия также должны обрабатываться на стороне сервера.