Ответ
JWT — это открытый стандарт (RFC 7519) для создания токенов доступа, которые используются для безопасной передачи информации между сторонами в виде JSON-объекта. Токен состоит из трех частей: заголовок (Header), полезная нагрузка (Payload) и подпись (Signature).
Плюсы:
- Stateless (отсутствие состояния на сервере): Серверу не нужно хранить информацию о сессиях. Вся необходимая информация (ID пользователя, роли) содержится в самом токене. Это упрощает архитектуру.
- Масштабируемость: Благодаря stateless-подходу, запросы с одним и тем же токеном могут обрабатываться любым экземпляром сервиса, что идеально для микросервисной архитектуры и балансировки нагрузки.
- Целостность данных: Подпись (Signature) гарантирует, что данные в токене не были изменены в пути. Сервер, зная секретный ключ, может проверить подлинность токена.
- Кросс-доменность (CORS): JWT легко передавать в заголовках HTTP, что делает его удобным для взаимодействия между разными доменами и сервисами (например, веб-клиент на
site.com
и API наapi.site.com
).
Минусы и риски:
- Невозможность принудительного отзыва: Главный недостаток. Если токен украден, он будет действителен до истечения своего срока (
exp
). Решение: использовать короткоживущие access-токены (5-15 минут) и долгоживущие refresh-токены для их обновления. - Размер: JWT обычно больше, чем ID сессии в cookie, так как содержит данные. Это может незначительно увеличить трафик, особенно при передаче с каждым запросом.
- Безопасность хранения на клиенте:
- localStorage: Уязвим для XSS-атак (любой скрипт на странице может получить доступ к токену).
- Cookies: Более безопасный вариант, если использовать флаг
HttpOnly
(недоступен из JavaScript) иSecure
(передача только по HTTPS).
- Данные в Payload не зашифрованы: Содержимое полезной нагрузки (Payload) просто закодировано в Base64Url и легко читается кем угодно. Никогда не храните в JWT чувствительные данные (пароли, личную информацию)! Для шифрования используется другой стандарт — JWE (JSON Web Encryption).
// Пример создания JWT с использованием библиотеки github.com/golang-jwt/jwt
import (
"time"
"github.com/golang-jwt/jwt/v4"
)
// Секретный ключ должен храниться безопасно, например, в переменных окружения
var jwtKey = []byte("my_secret_key")
func createToken(userID int) (string, error) {
// Устанавливаем срок жизни токена
expirationTime := time.Now().Add(15 * time.Minute)
// Создаем полезную нагрузку (claims)
claims := &jwt.RegisteredClaims{
Subject: string(userID),
ExpiresAt: jwt.NewNumericDate(expirationTime),
}
// Создаем токен с указанием алгоритма подписи и claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Подписываем токен нашим секретным ключом
return token.SignedString(jwtKey)
}