Перейти к содержанию

Web3: смена аккаунта, выход и отзыв сессии

Оглавление курса «Web3: вход, смарт-аккаунты и индексатор» · Урок 8 из 30.

Пользователь может переключить аккаунт кошелька, закрыть кабинет или отозвать сессии на другом устройстве. Эти действия имеют разный смысл. В этом уроке разделим состояние провайдера и серверной сессии, реализуем выход и определим маршрут повторного входа. Результат — кабинет не приписывает прежнюю сессию новому адресу только из-за смены расширения.

Предполагаются cookie и серверное хранилище сессий предыдущего урока. Реальные запросы и программы не запускались. Учебная библиотека хранит прогресс курса17 вне цепочки; вход и выход не публикуют события CourseCatalog и не изменяют publisher.

Два разных источника состояния

Кошелёк сообщает текущий адрес браузеру. Сервер сообщает адрес действующей сессии. Эти значения могут различаться после переключения. Если интерфейс сразу заменит заголовок кабинета адресом кошелька, он будет показывать чужой профиль поверх прежней cookie. Это визуальная и логическая ошибка, даже когда сервер правильно защищает данные.

Кабинет отображает адрес, проверенный сервером. При несовпадении с выбранным кошельком появляется сообщение и явный маршрут смены пользователя. Обычно сначала выполняется выход или замена сессии по политике, затем новый challenge для нового адреса. Старый пользовательский прогресс не переносится автоматически другому аккаунту.

Подключение кошелька может отсутствовать, а серверная сессия ещё быть действительной. Для обычного просмотра кабинета это допустимо, если такова политика сервиса. Чувствительное действие может потребовать свежего подтверждения. Не нужно автоматически запрашивать аккаунты на каждой загрузке только ради сохранения обычного веб-сеанса.

Серверный выход

Выход выполняет изменяющий запрос с текущей сессией и защитой origin/CSRF. Сервер отзывает запись, затем удаляет cookie с соответствующими областью и флагами. Пустая строка в клиентском состоянии не отзывает серверный идентификатор, поэтому один setUser(null) недостаточен.

Set-Cookie: __Host-library_session=; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=0

Это заголовок удаления для той же cookie-политики. Если исходная cookie имела другое имя или область, удаление должно соответствовать ей. Нельзя считать произвольный новый заголовок гарантией очистки всех старых вариантов. Сервис сохраняет одну понятную схему и не создаёт несколько конкурирующих идентификаторов без необходимости.

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

Сбой во время выхода

Если сеть отказала до подтверждённого отзыва, интерфейс не может безоговорочно обещать, что все серверные полномочия исчезли. Он может скрыть локальные персональные данные и предложить повторить выход. В модели состояния отдельно отмечается, что завершение серверного действия не подтверждено. Это честнее универсального «Вы вышли», после которого прежняя cookie ещё действует.

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

Удаление локального кеша персональных данных также входит в маршрут. Иначе после выхода карточки прогресса останутся на экране или будут показаны следующему пользователю устройства. Публичный кеш статей можно сохранить: он не принадлежит конкретной сессии. Такая разница важна для сайта, где большая часть материала открытая.

Несколько вкладок

Вторая вкладка может всё ещё показывать кабинет после выхода в первой. Сервер уже отвергает её запросы, но интерфейс должен обновить состояние. Можно уведомить вкладки того же origin через BroadcastChannel и перечитать серверный статус. Сообщение канала не является самостоятельным доказательством отзыва, а помогает синхронизировать представление.

Персональный query-кеш очищается или связывается с идентификатором поколения сессии. Нельзя использовать одинаковый ключ progress:17 для разных вошедших аккаунтов без разделения. После смены пользователя старый результат может прийти поздно, поэтому применяется знакомое правило поколения и отмены применения устаревшего ответа.

Транзакции, отправленные прежним аккаунтом до выхода, остаются в своей сетевой истории. Серверный logout не отменяет publish и не удаляет receipt. Публичный журнал операции может быть доступен отдельно, а персональные сведения кабинета очищаются. Смешение этих данных создало бы ложное ощущение, что выход отменил действие цепочки.

Отзыв всех сессий

Для функции «Выйти на всех устройствах» сервер отзывает несколько записей выбранного аккаунта по своей политике. Это более чувствительное действие и может требовать свежего подтверждения. Обычная cookie одной вкладки не является списком всех устройств. Хранилище содержит идентификаторы сессий и управляет их действительностью.

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

Повторный вход

Новый аккаунт получает новый challenge и новую сессию. Старое подписанное сообщение не используется для удобного переключения: nonce уже потреблён. Даже если пользователь вернулся к исходному адресу, новый вход доказывает текущий контроль в новом потоке. Прежние записи прогресса связываются с адресом по серверной модели, а не с историей кнопок кошелька.

На экране смены пользователя ясно показано, какой аккаунт сейчас имеет сессию и какой выбран в расширении. Пользователь выбирает действие, а приложение не спрашивает подпись неожиданно в ответ на любое accountsChanged. Это сохраняет принцип явного согласия из курса интерфейса.

Для упражнения рассмотрите смену A→B, выход в другой вкладке и потерянный ответ logout. Запишите отдельно сетевой кошелёк, серверную запись и локальный кеш. Ожидаемый итог — каждый источник обновляется по своей процедуре, а прежняя сессия не становится сессией B. Рекомендации отзыва описаны в OWASP Session Management.

Возврат после выхода

Кнопка браузера «Назад» может показать ранее сохранённое представление кабинета. Следующее обращение к персональным данным всё равно проверяет серверную сессию. UI не должен доверять старому экрану как разрешению действия. При возвращении на приватный маршрут обновляется статус входа, а данные защищаются политикой кеширования.

Оглавление серии