JavaRush /Курсы /Модуль 3: React /Хранение JWT в localStorage и sessionStorage

Хранение JWT в localStorage и sessionStorage

Модуль 3: React
15 уровень , 4 лекция
Открыта

Почему важно правильно хранить JWT?

Раз уж мы начали говорить об аутентификации, возникает вопрос: где хранить наш драгоценный токен? Вариантов много, но мы рассмотрим два самых популярных — localStorage и sessionStorage. Однако, важно понимать, что выбор места для хранения токена напрямую влияет на безопасность вашего приложения.

Чего стоит бояться

  1. XSS (межсайтовый скриптинг): если злоумышленник внедрит вредоносный скрипт в ваш код, токен в localStorage может стать доступным для кражи.
  2. CSRF (межсайтовая подделка запроса): при неправильной настройке серверов некоторые схематические уязвимости можно использовать против вас, но чаще это затрагивает cookie.

Итак, давайте посмотрим, как localStorage и sessionStorage работают, и разберём их плюсы и минусы.

LocalStorage vs SessionStorage: Чем они отличаются?

Характеристика localStorage sessionStorage
Срок хранения Данные хранятся «навсегда» (или до явного удаления). Данные удаляются при закрытии вкладки браузера.
Глобальная доступность Доступно между вкладками одного и того же домена. Доступно только в рамках одной вкладки.
Объём хранилища Обычно до 5 МБ. Обычно до 5 МБ.

Зная это, вы можете выбрать место хранения в зависимости от сценария. Например, если сессии пользователя должны быть недолгими, sessionStorage подойдёт идеально. Если же требуется кэшировать авторизацию на более долгий срок, можно воспользоваться localStorage.

Хранение токенов в localStorage

Итак, давайте начнём с простого примера, как хранить наши токены в localStorage.

Для этого мы можем использовать встроенные методы localStorage.setItem.

// Сохраняем токен в localStorage
const saveToken = (token: string): void => {
  localStorage.setItem('authToken', token);
};

Извлечение токена

Для получения значения используем localStorage.getItem.

// Получаем токен из localStorage
const getToken = (): string | null => {
  return localStorage.getItem('authToken');
};

Удаление токена

Если пользователь разлогинился, токен нужно удалить.

// Удаляем токен из localStorage
const removeToken = (): void => {
  localStorage.removeItem('authToken');
};

Пример использования в сервисе

Ваш AuthService может выглядеть примерно так:

class AuthService {
  private static TOKEN_KEY = 'authToken';

  static saveToken(token: string): void {
    localStorage.setItem(AuthService.TOKEN_KEY, token);
  }

  static getToken(): string | null {
    return localStorage.getItem(AuthService.TOKEN_KEY);
  }

  static removeToken(): void {
    localStorage.removeItem(AuthService.TOKEN_KEY);
  }
}

Теперь AuthService предоставляет удобные методы для работы с токенами.

Хранение токенов в sessionStorage

Работа с sessionStorage аналогична. Просто заменяем localStorage на sessionStorage. Например:

Сохранение токена

// Сохраняем токен в sessionStorage
const saveToken = (token: string): void => {
  sessionStorage.setItem('authToken', token);
};

Извлечение токена

// Получаем токен из sessionStorage
const getToken = (): string | null => {
  return sessionStorage.getItem('authToken');
};

Удаление токена

// Удаляем токен из sessionStorage
const removeToken = (): void => {
  sessionStorage.removeItem('authToken');
};

Пример для AuthService

Вы можете расширить наш AuthService так, чтобы он поддерживал оба хранилища:

class AuthService {
  private static TOKEN_KEY = 'authToken';

  static saveToken(token: string, useSession: boolean = false): void {
    if (useSession) {
      sessionStorage.setItem(AuthService.TOKEN_KEY, token);
    } else {
      localStorage.setItem(AuthService.TOKEN_KEY, token);
    }
  }

  static getToken(useSession: boolean = false): string | null {
    return useSession
      ? sessionStorage.getItem(AuthService.TOKEN_KEY)
      : localStorage.getItem(AuthService.TOKEN_KEY);
  }

  static removeToken(useSession: boolean = false): void {
    if (useSession) {
      sessionStorage.removeItem(AuthService.TOKEN_KEY);
    } else {
      localStorage.removeItem(AuthService.TOKEN_KEY);
    }
  }
}

Теперь вы можете выбирать, в какое хранилище сохранять токен!

Безопасность при хранении токенов

А теперь о важном: токены в localStorage или sessionStorage не зашифрованы. Это означает, что они видны через инструменты разработчика. Да, вы можете написать логику скрытия, но это не панацея.

Рассмотрим несколько советов по безопасности:

Выбор хранилища

Если данные крайне критичны (например, доступ к банкам), подумайте о хранении токенов в HttpOnly cookies, а не в localStorage. Такие куки недоступны из JavaScript, что значительно снижает риск XSS-атак.

Использование HTTPS

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

Ограничение времени действия токена

Всегда используйте короткоживущие токены (например, 15-30 минут), чтобы даже в случае их кражи ущерб был минимальным.

FAQ: что выбрать — localStorage или sessionStorage?

  1. Когда использовать localStorage?

    • Когда вы хотите, чтобы пользователь оставался залогиненным даже после закрытия браузера.
  2. Когда использовать sessionStorage?

    • Когда вы хотите, чтобы пользователь автоматически разлогинивался при закрытии вкладки.
  3. А если безопасность — приоритет?

    • Тогда используйте HttpOnly cookies. Это наиболее безопасный способ хранения токенов.

Как это выглядит в приложении?

В нашем проекте есть страница логина. После успешного входа мы сохраняем токен в localStorage и используем его для последующих запросов.

const login = async (username: string, password: string) => {
  try {
    const response = await fetch('/api/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
    });

    if (!response.ok) {
      throw new Error('Failed to login');
    }

    const { token } = await response.json();
    AuthService.saveToken(token);
    console.log('Logged in!');
  } catch (error) {
    console.error('Error during login:', error);
  }
};

Теперь вы знаете, как хранить JWT в клиенте. Как видите, всё не так уж сложно, но требует понимания нюансов и мер предосторожности.

2
Задача
Модуль 3: React, 15 уровень, 4 лекция
Недоступна
Сохранение токена в localStorage
Сохранение токена в localStorage
3
Опрос
Аутентификация с JWT, 15 уровень, 4 лекция
Недоступен
Аутентификация с JWT
Аутентификация с JWT
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ