Autorización y autenticación en Rust: guía completa para desarrolladores
Rust es un lenguaje de programación de sistemas que está ganando popularidad para la creación de servicios web seguros y de alta carga. Sin embargo, la implementación de autenticación (verificación de identidad) y autorización (verificación de permisos) en Rust requiere un enfoque especial debido a su estricto sistema de tipos y la falta de soluciones integradas. En este artículo, analizaremos las bibliotecas clave y ejemplos prácticos.
¿Por qué Rust para autenticación?
La seguridad es la principal prioridad de Rust. El compilador previene fugas de memoria, condiciones de carrera y muchas vulnerabilidades típicas de C/C++. Sin embargo, implementar la autenticación manualmente puede provocar errores, por lo que la comunidad ha creado varias bibliotecas maduras.
Bibliotecas principales para autenticación en Rust
1. actix-web-httpauth — para el framework web Actix-web
La biblioteca más popular para implementar autenticación HTTP (Basic, Bearer, Digest) en el ecosistema Actix-web.
2. jsonwebtoken — trabajo con JWT
Implementación completa de JSON Web Tokens (JWT) para Rust. Soporta RS256, HS256, ES256 y otros algoritmos.
3. bcrypt — hash de contraseñas
Biblioteca confiable para hash de contraseñas con el algoritmo bcrypt y generación automática de sal.
4. argon2 — hash moderno
Si bcrypt parece obsoleto, use Argon2, el ganador del concurso Password Hashing Competition.
5. tower-http — middleware para autorización
Permite crear middleware reutilizable para verificar permisos de acceso en cualquier servidor HTTP basado en Tower.
Ejemplo práctico: autenticación mediante JWT en Actix-web
Veamos un ejemplo mínimo de servidor con registro e inicio de sesión. Primero, agregue las dependencias en Cargo.toml:
[dependencies]actix-web = "4"actix-web-httpauth = "0.8"jsonwebtoken = "9"bcrypt = "0.15"serde = { version = "1", features = ["derive"] }tokio = { version = "1", features = ["full"] }Ahora escribamos la estructura del usuario y las funciones para crear/verificar JWT:
use actix_web::{web, App, HttpServer, HttpResponse, HttpRequest};use actix_web_httpauth::extractors::bearer::BearerAuth;use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use bcrypt::{hash, verify, DEFAULT_COST};use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct Claims { sub: String, // email del usuario exp: usize, // tiempo de expiración del token}
#[derive(Debug, Serialize, Deserialize)]struct User { email: String, password_hash: String,}
// Almacenamiento de usuarios (en la realidad — base de datos)static USERS: once_cell::sync::Lazy<std::sync::Mutex<Vec<User>>> = once_cell::sync::Lazy::new(|| std::sync::Mutex::new(vec![]));
async fn register(info: web::Json<UserInput>) -> HttpResponse { let hashed = hash(&info.password, DEFAULT_COST).unwrap(); let user = User { email: info.email.clone(), password_hash: hashed, }; USERS.lock().unwrap().push(user); HttpResponse::Ok().json("Usuario registrado")}
async fn login(info: web::Json<UserInput>) -> HttpResponse { let users = USERS.lock().unwrap(); if let Some(user) = users.iter().find(|u| u.email == info.email) { if verify(&info.password, &user.password_hash).unwrap() { let claims = Claims { sub: info.email.clone(), exp: 10000000000, }; let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(b"clave_secreta"), ).unwrap(); return HttpResponse::Ok().json(token); } } HttpResponse::Unauthorized También en la biblioteca
better-sqlite3-typescript para TypeScript: guía completa con ejemplos
Trabajo con fechas en Swift: Foundation y DateFormatter
Pruebas en C++: visión general de frameworks y herramientas (Google Test, Catch2, doctest)
Procesamiento de imágenes en Rust: resize y crop con image y imageproc