OAuth 2.0 和 JWT 授权在 Rust 上的完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程
```html

Rust 中的 OAuth 2.0 和 JWT 简介



现代 Web 应用程序需要可靠且安全的身份验证。该领域的两个关键标准是 OAuth 2.0(授权协议)和 JWT(JSON Web Token,一种访问令牌格式)。Rust 凭借其高性能和内存安全性,成为构建对速度和可靠性要求极高的 API 的绝佳选择。



在本文中,我们将探讨如何使用流行的 crate 在 Rust 中实现 OAuth 2.0 和 JWT 授权。您将学习如何配置服务器、签发和验证 JWT 令牌,以及集成 OAuth 2.0 流程。本文面向熟悉 Rust 基础和 Web 框架的开发者。



OAuth 2.0 和 JWT 的核心概念



什么是 OAuth 2.0?

OAuth 2.0 是一种委托访问协议。它允许应用程序在不传递用户凭证(用户名和密码)的情况下,获取对用户资源的有限访问权限。主要参与者包括:

  • Resource Owner — 拥有数据的用户。
  • Client — 我们的应用程序(例如,基于 Rust 的 Web 服务)。
  • Authorization Server — 在成功认证后颁发令牌的服务器。
  • Resource Server — 提供受保护数据的 API。


什么是 JWT?

JWT 是一种紧凑的、URL 安全的令牌格式,由三部分组成:头部(header)、载荷(payload)和签名(signature)。签名保证了数据的完整性。JWT 通常用作 OAuth 2.0 中的访问令牌(access token),因为它是自包含的:服务器无需查询数据库即可验证它。



Rust 中的实践实现

为了实现,我们需要以下 crate:

  • actix-web — Web 框架。
  • serde 和 serde_json — 用于序列化/反序列化。
  • jsonwebtoken — 用于处理 JWT。
  • dotenv — 用于管理配置。
  • chrono — 用于处理日期和时间。


步骤 1:项目设置与结构

创建一个新的 Cargo 项目,并在 Cargo.toml 中添加依赖:

[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"jsonwebtoken = "9"dotenv = "0.15"chrono = { version = "0.4", features = ["serde"] }uuid = { version = "1", features = ["v4"] }


创建 .env 文件来存储密钥:

JWT_SECRET=my_super_secret_key_12345


步骤 2:创建数据模型和 JWT 函数

定义 JWT 的结构体,并实现创建和验证令牌的函数。

use chrono::{Utc, Duration};use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Deserialize, Serialize};use std::env;

#[derive(Debug, Serialize, Deserialize)]pub struct Claims { pub sub: String, // 用户标识符 pub exp: usize, // 过期时间(时间戳) pub iat: usize, // 签发时间(时间戳)}

pub fn create_jwt(user_id: &str) -> Result<String, jsonwebtoken::errors::Error> { let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); 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, &EncodingKey::from_secret(secret.as_bytes()), )?; Ok(token)}

pub fn validate_jwt(token: &str) -> Result<Claims, jsonwebtoken::errors::Error> { ```

博客

书籍推荐