引言:为什么 Rust 需要授权?
现代 Web 应用程序很少能脱离身份验证和授权系统。Rust 凭借其高性能和内存安全性,正成为构建高负载服务的热门选择。然而,对于初学者来说,处理 OAuth 2.0 等协议和 JWT 格式可能显得复杂。
在本文中,我们将解析 OAuth 2.0 和 JWT(JSON Web Token)的基本概念,并使用流行的 crate 在 Rust 中实现一个简单的授权系统。您将学习如何保护您的 API 端点以及如何处理访问令牌。
什么是 OAuth 2.0 和 JWT?
在编写代码之前,理解理论很重要。
OAuth 2.0:委托访问协议
OAuth 2.0 是一种协议,允许应用程序在不传递用户登录名和密码的情况下,获得对用户资源的有限访问权限。想象一下,您想通过 Google 或 GitHub 登录网站——这就是 OAuth 2.0。
协议的主要参与者:
- 资源所有者 — 拥有数据的用户。
- 客户端 — 您的 Rust 应用程序,想要获取访问权限。
- 授权服务器 — 颁发令牌的服务器(例如 Google)。
- 资源服务器 — 提供数据的 API(例如 Google Drive)。
JWT:紧凑的令牌格式
JWT(JSON Web Token)是一种用于创建访问令牌的开放标准。令牌由三部分组成,用点分隔:
- 头部 — 令牌类型和签名算法。
- 负载 — 数据(声明),例如用户 ID 或角色。
- 签名 — 确保令牌未被篡改的签名。
JWT 示例:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNrxP0G7n9G4W7N8Y7J8
JWT 的便利之处在于它不需要在服务器上存储会话——所有信息都已嵌入令牌中。
为授权设置 Rust 项目
我们将使用 Actix Web 框架和几个辅助 crate。创建一个新项目:
cargo new rust-auth-examplecd rust-auth-example在 Cargo.toml 中添加依赖项:
[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"jsonwebtoken = "9"chrono = { version = "0.4", features = ["serde"] }dotenv = "0.15"env_logger = "0.10"bcrypt = "0.15"文件结构
为了方便,我们将创建一个模块化结构:
src/├── main.rs├── auth.rs├── models.rs└── handlers.rs在 .env 中写入 JWT 的密钥:
JWT_SECRET=supersecretkey12345DATABASE_URL=sqlite://users.db在 Rust 中实现 JWT:从生成到验证
从负责处理 JWT 的 auth.rs 模块开始。
JWT 的结构体
// auth.rsuse serde::{Deserialize, Serialize};use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use chrono::{Utc, Duration};
#[derive(Debug, Serialize, Deserialize)]pub struct Claims { pub sub: String, // 用户 ID pub exp: usize, // 过期时间 pub iat: usize, // 签发时间}
pub fn create_jwt(user_id: &str, secret: &str) -> Result<String, jsonwebtoken::errors::Error> { let now = Utc::now(); let expiration = now + Duration::hours(24); // 令牌有效期为 24 小时
let claims = Claims { sub: user_id.to_owned(), exp: expiration.timestamp() as usize, iat: now.timestamp() as usize, };
let token = encode( &Header::default(), &claims,\