JWT токены в Rust: библиотека jsonwebtoken и работа с аутентификацией

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

JWT токены в Rust: библиотека jsonwebtoken

JSON Web Tokens (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанных на JSON. В экосистеме Rust одной из самых популярных и стабильных библиотек для работы с JWT является jsonwebtoken. Она предоставляет полный набор функций для создания, подписи, верификации и декодирования JWT токенов, поддерживая как симметричные (HS256, HS384, HS512), так и асимметричные (RS256, RS384, RS512, ES256, ES384) алгоритмы шифрования.

Установка и настройка

Для начала работы добавьте зависимость в файл Cargo.toml вашего проекта:

[dependencies]
jsonwebtoken = "9.3"
serde = { version = "1.0", features = ["derive"] }
chrono = "0.4"

Библиотека serde необходима для сериализации и десериализации данных токена, а chrono упрощает работу с временными метками (exp, iat, nbf).

Базовая структура JWT

JWT токен состоит из трех частей: заголовок (header), полезная нагрузка (claims) и подпись. В Rust это реализуется через структуры:

use serde::{Serialize, Deserialize};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,      // субъект (обычно ID пользователя)
    exp: usize,       // время истечения (unix timestamp)
    iat: usize,       // время создания (unix timestamp)
    role: String,     // кастомное поле
}

Создание и подпись JWT токена

Рассмотрим полный пример создания токена с использованием алгоритма HS256 (симметричное шифрование):

use jsonwebtoken::{encode, Header, EncodingKey};
use chrono::Utc;

fn create_jwt(user_id: &str, secret: &str) -> Result {
    let now = Utc::now().timestamp() as usize;
    let claims = Claims {
        sub: user_id.to_string(),
        exp: now + 3600,  // токен действителен 1 час
        iat: now,
        role: "user".to_string(),
    };

    let token = encode(
        &Header::default(),  // по умолчанию HS256
        &claims,
        &EncodingKey::from_secret(secret.as_bytes()),
    )?;
    Ok(token)
}

Верификация и декодирование токена

Для проверки подлинности токена используется функция decode с указанием алгоритма и секретного ключа:

use jsonwebtoken::{decode, DecodingKey, Validation, Algorithm};

fn verify_jwt(token: &str, secret: &str) -> Result {
    let validation = Validation::new(Algorithm::HS256);
    let token_data = decode::(
        token,
        &DecodingKey::from_secret(secret.as_bytes()),
        &validation,
    )?;
    Ok(token_data.claims)
}

Работа с асимметричными алгоритмами (RS256)

Для production-среды рекомендуется использовать асимметричное шифрование. Пример с RS256:

use jsonwebtoken::{encode, decode, Header, EncodingKey, DecodingKey, Validation, Algorithm};

// Создание токена с приватным ключом
fn create_rs256_token(user_id: &str, private_key_pem: &str) -> Result> {
    let claims = Claims {
        sub: user_id.to_string(),
        exp: (Utc::now().timestamp() + 3600) as usize,
        iat: Utc::now().timestamp() as usize,
        role: "admin".to_string(),
    };

    let token = encode(
        &Header::new(Algorithm::RS256),
        &claims,
        &EncodingKey::from_rsa_pem(private_key_pem.as_bytes())?,
    )?;
    Ok(token)
}

// Верификация с публичным ключом
fn verify_rs256_token(token: &str, public_key_pem: &str) -> Result> {
    let mut validation = Validation::new(Algorithm::RS256);
    validation.validate_exp = true;  // проверка срока действия

    let token_data = decode::(
        token,
        &DecodingKey::from_rsa_pem(public_key_pem.as_bytes())?,
        &validation,
    )?;
    Ok(token_data.claims)
}

Расширенные возможности и валидация

Библиотека предоставляет тонкую настройку валидации через структуру Validation:

use jsonwebtoken::Validation;

// Кастомная валидация
fn custom_validation() -> Validation {
    let mut validation = Validation::new(Algorithm::HS256);
    validation.leeway = 60;              // допустимое отклонение во времени (сек)
    validation.validate_exp = true;       // проверять exp
    validation.validate_iat = true;       // проверять iat
    validation.required_specific_claims                    

Рекомендаций