返回首页

Rust 上授权服务的开发:令牌、加密、Redis

本文致力于 Rust 上授权服务的开发,涵盖 JWT 和不透明令牌的生成、使用非对称加密进行验证以及在 Redis 中的存储。该材料包括实用代码示例和潜在漏洞讨论。

如何在 Rust 上构建授权服务:从基础到高级技巧
Advertisement 728x90

用 Rust 构建安全认证服务:令牌、加密与 Redis

在 Rust 中打造一个可靠的认证服务,需要深入理解密码学、令牌管理和巧妙的抽象设计。本文基于实战经验,详细讲解 JWT 和不透明令牌的生成、验证,以及 Redis 存储。

令牌架构与生成

服务采用两种令牌:访问令牌(JWT)用于短期会话,刷新令牌(不透明)实现无缝续期,无需重新认证。

JWT 令牌使用 RS256 非对称加密算法,签名需私钥,验证用公钥。不透明令牌是随机 base64 字符串,不含客户端可读信息,提升安全性。

Google AdInline article slot

密钥生成组件

  • JwtTokenProvider:用于基于声明和私钥生成 JWT 的 trait。
  • OpaqueTokenProvider:通过随机字节生成不透明令牌的 trait。
  • Claims 结构:包含标准字段,如 sub(用户 ID)、jti(令牌 ID)、iat(签发时间)和 exp(过期时间)。

JwtTokenProvider 示例实现:

pub trait IJwtTokenProvider {
    type Claims: Send + Sync;
    type Error;
    fn generate(&self, claims: &Self::Claims, pem: &str) -> Result<String, Self::Error>;
}

令牌验证与校验

JWT 验证使用公钥防范私钥泄露。IJwtTokenValidator trait 处理签名检查和令牌完整性。

验证要点

  • PEM 格式:密钥存储在 PEM 文件中,支持证书和信任链。
  • 加密算法:支持对称(如 HS256)和非对称(如 RS256),优先后者以提升安全。
  • 声明转换:领域模型适配库要求,如 DateTime 转为 usize。

验证代码示例:

Google AdInline article slot
pub trait IJwtTokenValidator {
    type Claims: Send + Sync;
    type Error;
    fn verify(&self, token: &str, pem: &str) -> Result<Self::Claims, Self::Error>;
}

令牌存储与协调

TokenManager 和 KeyManager 管理令牌与密钥。TokenManager 生成、验证并将令牌存入 Redis,利用灵活抽象。

RedisIO 实现

RedisIO 简化存储操作,提供 setex、get 和 delete 方法,减少样板代码,提高可读性。

示例:

Google AdInline article slot
impl<Storage> RedisIO<Storage>
where Storage: redis::AsyncCommands + Send + Sync
{
    pub async fn setex(&mut self, key: &str, data: &str, exp: u64) -> Result<(), redis::RedisError> {
        self.redis_storage.set_ex::<&str, String, (>(&key, data.to_string(), exp).await?;
        Ok(())
    }
}

TokenManager 特性

使用泛型支持提供者和验证器,便于替换。主要方法:

  • generate_pair:生成访问/刷新令牌对,存入 Redis 并设置 TTL。
  • verify_access:校验访问令牌存在性和完整性。

使用示例:

pub async fn generate_pair(&mut self, claims: &Claims, pem: &str) -> Result<(String, String), TokenManagerError> {
    let access_token = self.access_provider.generate(&claims, &pem)?;
    let refresh_token = self.refresh_provider.generate();
    // Redis 存储逻辑
    Ok((access_token, refresh_token))
}

核心要点

  • RS256 非对称加密让 JWT 安全性远超对称方法。
  • 不透明令牌作为随机 base64 字符串,难以伪造。
  • Trait 便于测试和替换组件。
  • Redis TTL 存储高效管理会话,减轻数据库压力。
  • 严格分离公私钥,避免泄露风险。

常见问题与解决方案

开发中发现的问题:

  • Base64 膨胀:32 字节扩展至 43 字节,可能引发存储问题。
  • 密钥误用:验证时用私钥是大忌。
  • 类型不匹配:DateTime 转 usize 需要校验。

解决方案:

  • 测试各种数据大小的边界情况。
  • 强制严格的密钥类型/格式检查。
  • 借助成熟的 JWT/加密库。

— Editorial Team

Advertisement 728x90

继续阅读