- 新增 zclaw-saas crate 作为 workspace 成员 - 配置系统 (TOML + 环境变量覆盖) - 错误类型体系 (SaasError 16 变体, IntoResponse) - SQLite 数据库 (12 表 schema, 内存/文件双模式, 3 系统角色种子数据) - JWT 认证 (签发/验证/刷新) - Argon2id 密码哈希 - 认证中间件 (公开/受保护路由分层) - 账号管理 CRUD + API Token 管理 + 操作日志 - 7 单元测试 + 5 集成测试全部通过
49 lines
1.5 KiB
Rust
49 lines
1.5 KiB
Rust
//! 密码哈希 (Argon2id)
|
|
|
|
use argon2::{
|
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
|
Argon2,
|
|
};
|
|
|
|
use crate::error::{SaasError, SaasResult};
|
|
|
|
/// 哈希密码
|
|
pub fn hash_password(password: &str) -> SaasResult<String> {
|
|
let salt = SaltString::generate(&mut OsRng);
|
|
let argon2 = Argon2::default();
|
|
let hash = argon2
|
|
.hash_password(password.as_bytes(), &salt)
|
|
.map_err(|e| SaasError::PasswordHash(e.to_string()))?;
|
|
Ok(hash.to_string())
|
|
}
|
|
|
|
/// 验证密码
|
|
pub fn verify_password(password: &str, hash: &str) -> SaasResult<bool> {
|
|
let parsed_hash = PasswordHash::new(hash)
|
|
.map_err(|e| SaasError::PasswordHash(e.to_string()))?;
|
|
Ok(Argon2::default()
|
|
.verify_password(password.as_bytes(), &parsed_hash)
|
|
.is_ok())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_hash_and_verify() {
|
|
let hash = hash_password("correct_password").unwrap();
|
|
assert!(verify_password("correct_password", &hash).unwrap());
|
|
assert!(!verify_password("wrong_password", &hash).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_different_hashes_for_same_password() {
|
|
let hash1 = hash_password("same_password").unwrap();
|
|
let hash2 = hash_password("same_password").unwrap();
|
|
assert_ne!(hash1, hash2);
|
|
assert!(verify_password("same_password", &hash1).unwrap());
|
|
assert!(verify_password("same_password", &hash2).unwrap());
|
|
}
|
|
}
|