Ответ
JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для создания компактных и самодостаточных токенов, предназначенных для безопасной передачи информации между сторонами в виде JSON-объекта. Они часто используются для аутентификации и авторизации в API.
Структура JWT:
Токен состоит из трёх частей, разделённых точками (.):
header.payload.signature
- Header (Заголовок) — содержит метаданные: тип токена (
typ: "JWT") и используемый алгоритм подписи (alg: "HS256", "RS256" и т.д.). Кодируется в Base64Url. - Payload (Полезная нагрузка) — содержит утверждения (claims), то есть данные о пользователе и другую информацию. Бывают стандартные (
iss,sub,exp— срок действия) и произвольные (user_id,role). Также кодируется в Base64Url. - Signature (Подпись) — используется для проверки того, что токен не был изменён. Создаётся путём подписи закодированных
headerиpayloadс использованием секретного ключа (дляHS256) или приватного ключа (дляRS256).
Пример создания в Go (golang-jwt/jwt):
// Создаем claims (утверждения)
claims := jwt.MapClaims{
"user_id": 123,
"role": "admin",
"exp": time.Now().Add(time.Hour * 24).Unix(), // Токен живет 24 часа
}
// Создаем токен с указанием алгоритма и claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Подписываем токен секретным ключом
tokenString, err := token.SignedString([]byte("your_secret_key"))
Преимущества:
- Stateless: Серверу не нужно хранить информацию о сессиях, вся информация находится в токене.
- Компактность: Можно передавать в URL, заголовках (
Authorization: Bearer ...) или теле запроса.
Недостатки и способы их решения:
- Невозможно отозвать досрочно: Если токен украден, он будет действителен до истечения срока (
exp).- Решение: Использовать короткое время жизни токенов и Refresh-токены, либо вести "черный список" (blacklist) отозванных токенов, например, в Redis.
- Размер: Если в
payloadмного данных, токен может стать большим. - Безопасность: Секретный ключ должен храниться в строжайшей тайне. Любой, кто его знает, может подделать токен.
Ответ 18+ 🔞
А, ну вот, опять про эти ваши JWT-токены, блядь! Слушай, сейчас я тебе так разжую, что ты, сука, во сне их декодировать начнёшь. Это ж не ракетостроение, ёпта!
Представь себе, что тебе нужно передать записку через всю школу, чтобы тебя на входе пропустили. Но так, чтобы всякие пидоры её не подделали. Вот JWT — это и есть такая хитрая, блядь, записка, только для компьютеров.
Из чего эта хуйня состоит?
Токен — это три куска, склеенные точкой: голова.тело.подпись. Всё просто, как три рубля.
- Голова (Header). Тут написано, что это за хуйня и как её проверять. Типа: «Я — JWT, и подписана я алгоритмом HS256». Потом эту инфу кодируют в Base64, чтобы не мозолила глаза. Ничего секретного, чисто техническая болтовня.
- Тело (Payload). А вот тут уже интереснее, блядь! Это полезная нагрузка, или «клеймы». Туда можно накидать всё, что в голову взбредёт:
user_id,role, срок годности (exp). Всё, что серверу нужно знать о пользователе, не спрашивая базу данных каждые пять секунд. И эту простыню тоже кодируют в Base64. - Подпись (Signature). А вот это, сука, самый сок! Это что-то вроде печати или сургучной пломбы. Берут закодированные голову и тело, берут секретный ключ (который должен быть тайной, как пин-код от карты твоей бабки) и эту хуйню подписывают. Если хоть одну запятую в теле поменять — подпись не сойдётся, и токен превратится в тыкву, то есть в никчёмную хуйню.
Вот как эту радость на Go клепают (библиотека golang-jwt/jwt):
// Накидываем в тело всё, что душе угодно
claims := jwt.MapClaims{
"user_id": 123,
"role": "admin",
"exp": time.Now().Add(time.Hour * 24).Unix(), // Жить будет сутки, не вечно же, блядь
}
// Лепем токен, говорим, какой алгоритм и суём туда наши claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// А теперь, сука, самый ответственный момент — подписываем своим секретным ключом
tokenString, err := token.SignedString([]byte("твой_секретный_ключ_нахуй"))
if err != nil {
// Ошибка? Ну бля, значит, ключ кривой или ещё какая хуйня
}
Чем это всё охуенно?
- Stateless (Без состояния). Серверу не нужно, как дураку, помнить все сессии. Всё, что надо, уже в токене. Получил, проверил подпись — и в ус не дуешь. Масштабируется на ура.
- Компактность. Эту строку можно в заголовок воткнуть (
Authorization: Bearer <токен>), в URL сунуть — удобно, блядь.
А где, сука, подводные ебли?
- Не отзовёшь, блядь! Вот это главная засада. Украли у тебя токен? Ну всё, пиздец. Он будет работать, пока не истечёт его срок жизни (
exp). Представь, что ты потерял пропуск в клуб, а охранник-робот до самого утра всех с такими пропусками пускает.- Что делать? Либо делать срок жизни коротким, как у майского жука, и использовать refresh-токены для обновления. Либо завести чёрный список (blacklist) в какой-нибудь быстрой памяти типа Redis и туда складывать отозванные токены до их естественной смерти. Но это уже state, ёпта, обратно к сессиям почти.
- Размер. Если в payload накидать полбиографии пользователя, токен раздуется, как жаба. Каждый запрос будет таскать эту простыню туда-сюда.
- Безопасность. Секретный ключ — это святое! Если его спалят, то любой школьник сможет лепить токены от имени админа. Хранить его надо так, будто это последняя бутылка воды в пустыне.