Rust中的安全认证:编写受保护的后端

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

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

开始课程

为什么Rust是认证的理想选择?

\n\n

如果您正在用Rust编写Web应用程序,您在安全性方面已经领先一步。Rust不容忍内存错误,这意味着许多漏洞(缓冲区溢出、释放后使用)在编译阶段就被消除了。但编译器无法保护您免受糟糕的认证逻辑的影响。这正是本文要讨论的内容——如何使用现代实践构建Rust中的安全认证。

\n\n

在本文中,我们将构建一个完整的认证模块:通过bcrypt进行密码哈希、签发JWT令牌、在Actix-web中进行中间件检查以及防御常见攻击。代码是可运行的——您可以放心地将其用于您的项目。

\n\n

1. 密码哈希:为什么用bcrypt而不是SHA-256?

\n\n

许多初学者会想:“我用SHA-256吧,它又快又可靠。” 这是一个致命的错误。SHA是一种加密哈希函数,但它太快了。攻击者每秒可以尝试数十亿种组合。我们需要一个专门为密码设计的慢速函数。

\n\n

bcrypt是黄金标准。它包含“盐值”(salt)和“成本因子”(cost factor),后者可以随着计算能力的增长而增加。

\n\n

在Cargo.toml中添加bcrypt

\n
[dependencies]\nbcrypt = "0.15"
\n\n

哈希密码

\n
use bcrypt::{hash, verify, DEFAULT_COST};\n\nfn hash_password(plain: &str) -> Result<String, bcrypt::BcryptError> {\n    hash(plain, DEFAULT_COST) // cost = 12 (默认值)\n}\n\nfn verify_password(plain: &str, hashed: &str) -> bool {\n    verify(plain, hashed).unwrap_or(false)\n}
\n\n

请注意:verify会自动从哈希中提取盐值。您无需单独存储盐值——它已经包含在哈希字符串中。这既安全又方便。

\n\n

2. JWT令牌:如何避免认证失败

\n\n

用户输入密码后,我们需要发放一个“通行证”。JWT(JSON Web Token)是一种紧凑且自包含的格式。但魔鬼在细节中:

\n\n
    \n
  • 不要将密钥存储在代码中。 使用环境变量。
  • \n
  • 设置较短的过期时间。 访问令牌(Access Token)——15-30分钟,刷新令牌(Refresh Token)——7-30天。
  • \n
  • 不要在payload中包含敏感数据。 只包含用户ID和角色。
  • \n
\n\n

使用jsonwebtoken实现JWT

\n\n
use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};\nuse serde::{Serialize, Deserialize};\nuse chrono::{Utc, Duration};\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Claims {\n    pub sub: String,       // 用户ID\n    pub exp: usize,        // 过期时间戳\n    pub iat: usize,        // 签发时间\n}\n\npub fn create_token(user_id: &str, secret: &str) -> Result<String, jsonwebtoken::errors::Error> {\n    let now = Utc::now();\n    let claims = Claims {\n        sub: user_id.to_owned(),\n        exp: (now + Duration::minutes(30)).timestamp() as usize,\n        iat: now.timestamp() as usize,\n    };\n    encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()))\n}\n\npub fn validate_token(token: &str, secret: &str) -> Result<Claims, jsonwebtoken::errors::Error> {\n    let token_data = decode::<Claims>(\n        token,\n        &DecodingKey::from_secret(secret.as_bytes()),\n        &Validation::default(),\n    )?;\n    Ok(token_data.claims)\n}
\n\n

3. 整合所有内容:Actix-web + 中间件

\n\n

现在,我们将哈希和JWT整合到一个基于Actix-web的完整Web应用程序中。我们将编写一个中间件,用于在每个受保护的请求中检查令牌。

\n\n

项目结构

\n
src/\n├── main.rs\n├── auth.rs       # 哈希、JWT\n├── middleware.rs # 令牌检查\n└── handlers.rs   #                

博客

书籍推荐