← Назад к вопросам

Куда прописываешь токен?

1.3 Junior🔥 203 комментариев
#Soft Skills и рабочие процессы

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Места размещения токена авторизации в Frontend-приложениях

Как Frontend Developer с многолетним опытом, я рассматриваю размещение токена авторизации (чаще всего JWT — JSON Web Token) как критически важный архитектурный выбор, который напрямую влияет на безопасность, UX и производительность приложения. Токен — это ключ, открывающий доступ к API и защищенным ресурсам, и его необходимо хранить и передавать с максимальной осторожностью.

Основные подходы к хранению токена на клиенте

1. Local Storage / Session Storage

Наиболее простой, но и наиболее рискованный способ. Токен сохраняется в браузерном хранилище, которое доступно через JavaScript.

// Сохранение токена после успешной авторизации
const saveTokenToLocalStorage = (token) => {
    localStorage.setItem('auth_token', token);
};

// Получение токена для использования в запросах
const getTokenFromLocalStorage = () => {
    return localStorage.getItem('auth_token');
};

Проблемы этого метода:

  • Уязвимость к XSS (Cross-Site Scripting): Если в приложение внедрен вредоносный скрипт, он может легко получить токен из localStorage.
  • Токен не имеет "срока жизни" в контексте сессии браузера — остается после закрытия окна (в отличие от sessionStorage).

2. HTTP-only Cookies

Более безопасный подход. Токен устанавливается сервером в HTTP-only cookie, который недоступен для JavaScript на клиенте.

// Серверный код (пример, Node.js/Express)
app.post('/login', (req, res) => {
    // ... проверка логина/пароля
    const token = generateJWT(user);
    
    // Установка токена в HTTP-only cookie
    res.cookie('auth_token', token, {
        httpOnly: true,    // Недоступно через JS
        secure: true,      // Только через HTTPS
        sameSite: 'strict' // Защита от CSRF
    });
    res.json({ success: true });
});

Преимущества:

  • Защита от XSS: JavaScript не может прочитать этот cookie, следовательно, вредоносный скрипт не сможет его украсть.
  • Автоматическая отправка: Cookie автоматически прикрепляется к каждому запросу на тот же домен, не требуя явной логики на фронтенде.
  • Срок жизни контролируется параметрами cookie (expires, maxAge).

Недостатки/сложности:

  • Уязвимость к CSRF (Cross-Site Request Forgery): Необходимо дополнительно защищаться (используя sameSite атрибуты, CSRF-токены).
  • Сложнее работать с CORS: При обращении к API на другом домене/поддомене нужно явно настроить политику credentials.
  • Клиентский код не имеет прямого доступа к токену, что может затруднить некоторые сценарии (например, добавление его в заголовок для запроса к стороннему API).

3. Memory (In-memory storage) / State

Токен хранится исключительно в памяти приложения (например, в переменной, в состоянии React/Vue/и т.д.).

// Пример в React с использованием контекста или состояния
const AuthContext = createContext();

const AuthProvider = ({ children }) => {
    const [token, setToken] = useState(null);

    const login = async (credentials) => {
        const response = await fetch('/api/login', { ... });
        const { token } = await response.json();
        // Сохраняем только в памяти, НЕ в localStorage!
        setToken(token);
    };

    return (
        <AuthContext.Provider value={{ token, setToken }}>
            {children}
        </AuthContext.Provider>
    );
};

Преимущества:

  • Максимальная безопасность: Токен исчезает при закрытии или перезагрузке страницы. Не сохраняется нигде перманентно, недоступен для XSS.
  • Идеально для SPA с высокими требованиями безопасности.

Недостатки:

  • Плохой UX: Пользователь теряет авторизацию после каждого закрытия браузера или даже при простой перезагрузке страницы.
  • Необходимость частого повторного логина.

Где и как "прописывается" токен при отправке запросов?

Независимо от места хранения, для авторизации запросов к API токен необходимо включить в HTTP-заголовки.

Стандартный подход: заголовок Authorization

// Функция для создания авторизованного запроса
const makeAuthenticatedRequest = async (url, options = {}) => {
    const token = getToken(); // Получаем из памяти, контекста или (осторожно!) из localStorage
    
    const headers = {
        ...options.headers,
        'Authorization': `Bearer ${token}` // Классическая схема Bearer Token
    };

    return fetch(url, {
        ...options,
        headers
    });
};

// Использование
makeAuthenticatedRequest('/api/protected-data', {
    method: 'GET'
}).then(response => response.json());

Если токен в HTTP-only Cookie:

Заголовок Authorization часто не требуется, так как cookie автоматически отправляется браузером. Однако, для явного контроля или работы с CORS, его можно установить.

// Для запросов к API на другом домене необходимо явно включить credentials
fetch('https://another-domain.com/api/data', {
    method: 'GET',
    credentials: 'include' // Это позволит браузеру прикрепить HTTP-only cookie
});

Современные best practices и рекомендации

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

  • Для большинства корпоративных SPA: HTTP-only cookie + Secure + SameSite=Strict/Lax. Это обеспечивает хороший баланс безопасности (защита от XSS) и удобства (сессия сохраняется между перезагрузками, если cookie имеет достаточный maxAge). Необходимо дополнить защитой от CSRF.
  • Для мобильных гибридных приложений или микросервисных архитектур: Часто используется Bearer Token в заголовке Authorization, хранящийся в защищенном memory storage или в специализированных хранилищах, предоставляемых фреймворками (например, Secure Storage в React Native).
  • Никогда не храните токены (особенно refresh tokens) в localStorage без крайней необходимости и без дополнительных мер защиты (например, шифрования, которое само по себе сложно реализовать безопасно на клиенте).

Ключевой вывод: "Прописывание" токена — это не одна точка в коде. Это архитектурная цепочка: место безопасного хранения (cookie, память), механизм его получения (из контекста, из cookie) и способ его передачи в запросах (заголовок Authorization, автоматическая отправка cookie). Выбор зависит от триады Security — UX — Architecture вашего конкретного проекта.