Авторизация и аутентификация в Rust: от JWT до сессий
В мире системного и веб-программирования Rust завоевал репутацию безопасного и быстрого языка. Однако при создании веб-приложений разработчики часто сталкиваются с задачей реализации аутентификации (проверки подлинности пользователя) и авторизации (проверки прав доступа). В этой статье мы рассмотрим ключевые библиотеки и подходы для реализации этих механизмов в Rust, а также приведём практические примеры кода.
Основные концепции аутентификации и авторизации
Прежде чем перейти к инструментам, важно разграничить понятия:
- Аутентификация — процесс проверки, что пользователь тот, за кого себя выдаёт. Обычно выполняется с помощью логина/пароля, токенов или биометрии.
- Авторизация — определение того, какие ресурсы и действия доступны аутентифицированному пользователю. Часто реализуется через роли (администратор, модератор, пользователь) или права доступа.
В Rust оба процесса можно реализовать как на низком уровне (ручное управление токенами), так и с помощью готовых библиотек.
Популярные библиотеки для аутентификации в Rust
Для работы с сессиями и токенами в Rust существует несколько зрелых решений:
actix-identity— для управления сессиями в веб-фреймворке Actix-web. Поддерживает cookie-сессии и Redis.jsonwebtoken— библиотека для работы с JWT (JSON Web Tokens). Позволяет создавать, подписывать и верифицировать токены.argon2— реализация алгоритма хеширования паролей Argon2, рекомендованного OWASP.bcrypt— классическая библиотека для хеширования паролей.
Ниже мы рассмотрим каждый инструмент на примере.
Пример 1: Аутентификация с JWT и jsonwebtoken
JWT — один из самых популярных способов аутентификации в REST API. Токен содержит утверждения (claims) и подписывается секретным ключом. Рассмотрим базовую реализацию с помощью библиотеки jsonwebtoken.
// cargo add jsonwebtoken serde
use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String, // идентификатор пользователя
exp: usize, // время истечения (UNIX timestamp)
role: String, // роль пользователя
}
fn create_token(user_id: &str, role: &str) -> Result<String, jsonwebtoken::errors::Error> {
let claims = Claims {
sub: user_id.to_owned(),
exp: (chrono::Utc::now() + chrono::Duration::hours(24)).timestamp() as usize,
role: role.to_owned(),
};
encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(b"ваш_секретный_ключ")
)
}
fn verify_token(token: &str) -> Result<Claims, jsonwebtoken::errors::Error> {
let token_data = decode::<Claims>(
token,
&DecodingKey::from_secret(b"ваш_секретный_ключ"),
&Validation::default()
)?;
Ok(token_data.claims)
}
В этом примере мы создаём токен на 24 часа, содержащий ID пользователя и его роль. Функция verify_token проверяет подпись и возвращает claims, которые можно использовать для авторизации.
Пример 2: Хеширование паролей с Argon2
Никогда не храните пароли в открытом виде! Используйте Argon2 — современный и безопасный алгоритм хеширования.
// cargo add argon2
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use argon2::password_hash::{SaltString, rand_core::OsRng};
fn hash_password(password: &str) -> String {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
argon2.hash_password(password.as_bytes(), &salt)
.expect("Ошибка хеширования")
.to_string()
}
fn verify_password(password: &str, hash: &str) -> bool {
let parsed_hash = PasswordHash::new(hash).expect("Неверный формат хеша");
Argon2::default().verify_password(password.as_bytes(), &parsed_hash).is_ok()
}
Функция hash_password генерирует соль и возвращает строку хеша. verify_password проверяет пароль против сохранённого хеша.
Пример 3: Сессии в Actix-web с actix-identity
Для веб-приложений с традиционными сессиями удобно использовать
Также в библиотеке
Рекомендаций