perf(auth): offload Argon2 hash/verify to spawn_blocking
Argon2 是 memory-hard 计算,登录/注册时同步执行会阻塞 Tokio worker 数百毫秒。改为在阻塞线程池执行,JoinError 兜底任务 panic。
This commit is contained in:
parent
79cb809010
commit
62600a6687
@ -113,8 +113,14 @@ pub async fn register(
|
|||||||
|
|
||||||
let client = get_conn().await.map_err(AppError::db_conn)?;
|
let client = get_conn().await.map_err(AppError::db_conn)?;
|
||||||
|
|
||||||
let password_hash =
|
// Argon2 是 memory-hard 计算,必须在 spawn_blocking 中执行,避免阻塞 Tokio worker。
|
||||||
password::hash_password(&password).map_err(|_| AppError::Internal("密码处理失败"))?;
|
let pw_for_hash = password.clone();
|
||||||
|
let password_hash = tokio::task::spawn_blocking(move || {
|
||||||
|
password::hash_password(&pw_for_hash)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(|_| AppError::Internal("密码处理任务失败"))?
|
||||||
|
.map_err(|_| AppError::Internal("密码处理失败"))?;
|
||||||
|
|
||||||
// 使用 INSERT ON CONFLICT 原子性地完成“首个用户成为 admin”的竞争。
|
// 使用 INSERT ON CONFLICT 原子性地完成“首个用户成为 admin”的竞争。
|
||||||
// 若已有 admin 或用户名/邮箱冲突,RETURNING 将返回空。
|
// 若已有 admin 或用户名/邮箱冲突,RETURNING 将返回空。
|
||||||
@ -203,7 +209,14 @@ pub async fn login(username: String, password: String) -> Result<AuthResponse, S
|
|||||||
};
|
};
|
||||||
|
|
||||||
let password_hash: String = row.get("password_hash");
|
let password_hash: String = row.get("password_hash");
|
||||||
let valid = password::verify_password(&password, &password_hash)
|
// Argon2 校验同样在 spawn_blocking 中执行。
|
||||||
|
let pw_for_verify = password.clone();
|
||||||
|
let hash_for_verify = password_hash.clone();
|
||||||
|
let valid = tokio::task::spawn_blocking(move || {
|
||||||
|
password::verify_password(&pw_for_verify, &hash_for_verify)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(|_| AppError::Internal("密码处理任务失败"))?
|
||||||
.map_err(|_| AppError::Internal("密码处理失败"))?;
|
.map_err(|_| AppError::Internal("密码处理失败"))?;
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user