Ответ
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)
} Ответ 18+ 🔞
Так, слушай, про эти ваши JWT. Сижу тут, думаю, ну что за мода пошла — все как с ума посходили, везде их суют, прям панацея какая-то. А на деле-то, блядь, как всегда, не всё так радужно, ёпта.
Ну, JWT — это, грубо говоря, такая бумажка, билетик. Состоит из трёх кусков, склеенных точками. Первый — заголовок, там написано, какой алгоритм подписи. Второй — полезняк, там твой ID, роли, срок годности. Третий — подпись, чтобы не подделали. Всё это в JSON заворачивается и кодируется. Вроде бы красиво.
Чем хороши, эти ваши билетики?
- Stateless, ёбта! Серверу не нужно помнить, кто ты такой. Всё про тебя написано прямо в токене. Пришёл — показал билетик — тебя опознали. Серверу не нужно заводить на тебя папочку в памяти или в базе. Архитектура проще, голова не болит.
- Масштабируется, как сумасшедший. Раз серверу нихуя не надо помнить, то хоть тысяча серверов тебя примут. Кинул запрос на любой — он токен проверил и всё. Для микросервисов — просто песня.
- Не подделаешь. Подпись-то проверяется секретным ключом. Попробуй что-то в полезной нагрузке поменять — подпись не сойдётся, и тебя, пидораса шерстяного, нахуй пошлют.
- Междоменный. Кинул его в заголовок
Authorization: Bearer <токен>— и всё, лети себе междуfrontend.comиapi.backend.com. CORS только разреши.
А теперь, блядь, ложка дёгтя, размером с лопату. Минусы, на которых все обжигаются.
- Главная жопа — отозвать его нихуя нельзя. Украли у тебя токен? Ну всё, пиздец. Он будет работать, пока не истечёт срок. Это как потерять пропуск на завод — любой найдёт и пройдёт. Что делать? Делать токены короткоживущими, на 5-15 минут. А для обновления — отдельный, долгоживущий refresh-токен, который хранишь как зеницу ока и можешь отозвать в случае чего.
- Толстый он, сука. Не сравнить с какой-нибудь сессионной кукой. Тащить его в каждом запросе — трафик чуть подрастёт.
- Где хранить-то, мудя?
- В
localStorage? Да ты охренел? Любой XSS-скрипт на странице вытащит его и унесёт в закат. НИКОГДА. - В куках с
HttpOnlyиSecure? Вот это уже умнее. Из JS не достанешь, и летит только по HTTPS. Но тут свои танцы с CORS и CSRF начинаются. В общем, думай, блядь, голова дана не только для еды.
- В
- Данные не шифрованы, ёпта! Полезная нагрузка просто в Base64 закодирована. Раскодируй — и читай на здоровье. НИКОГДА НЕ ПИХАЙ ТУДА ПАРОЛИ, НОМЕРА КАРТОЧЕК И ПРОЧУЮ ХУЙНЮ! Это не для секретов. Хочешь секреты — смотри в сторону JWE.
// Вот, смотри, как на Go эту хрень генерить. Библиотека github.com/golang-jwt/jwt
import (
"time"
"github.com/golang-jwt/jwt/v5" // версия-то новая, блядь, v5
)
// Секретный ключ. Спрячь его, идиот! В переменные окружения, в спец. хранилище — куда угодно, только не в код.
var jwtKey = []byte("мой_супер_пупер_секрет_который_никто_не_угадает")
func слепитьТокен(userID int) (string, error) {
// Срок годности ставим. 15 минут — и в утиль.
expirationTime := time.Now().Add(15 * time.Minute)
// Полезная нагрузка. Subject — обычно ID юзера.
claims := &jwt.RegisteredClaims{
Subject: fmt.Sprintf("%d", userID), // Переводим int в string, а то обосрёшься
ExpiresAt: jwt.NewNumericDate(expirationTime),
}
// Лепим токен с алгоритмом HS256.
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Подписываем своим ключом. Всё, готово, неси на кассу.
return token.SignedString(jwtKey)
}
Вот и вся магия. Инструмент, в общем, мощный, но если им как молотком гвозди забивать — себе же пальцы отобьёшь. Думай, где и как применяешь, и про безопасность не забывай, а то охуеешь потом от последствий.