fix: 🔴 Refresh token 泄露 JWT_SECRET — 改用随机 UUID 替代 base64(secret)
Some checks failed
Deploy Backend / deploy (push) Has been cancelled
Some checks failed
Deploy Backend / deploy (push) Has been cancelled
This commit is contained in:
43
src/auth.rs
43
src/auth.rs
@@ -1,6 +1,6 @@
|
||||
use chrono::{Utc, Duration};
|
||||
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode};
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::AppError;
|
||||
use crate::models::{Claims, TempTokenClaims};
|
||||
@@ -11,7 +11,6 @@ use actix_web::{
|
||||
|
||||
// 常量
|
||||
const ACCESS_TOKEN_EXPIRE_HOURS: i64 = 24;
|
||||
const REFRESH_TOKEN_EXPIRE_DAYS: i64 = 7;
|
||||
|
||||
pub async fn jwt_middleware<B: MessageBody>(
|
||||
req: ServiceRequest,
|
||||
@@ -65,42 +64,10 @@ pub fn generate_token(
|
||||
.map_err(|e| format!("生成JWT失败: {}", e))
|
||||
}
|
||||
|
||||
// 生成 refresh_token(简单 base64 编码的随机字符串)
|
||||
pub fn generate_refresh_token(user_id: i32, secret: &str) -> Result<String, String> {
|
||||
let now = Utc::now();
|
||||
let exp = (now + Duration::days(REFRESH_TOKEN_EXPIRE_DAYS)).timestamp();
|
||||
|
||||
let payload = format!("{}:{}:{}", user_id, exp, secret);
|
||||
let token = BASE64.encode(payload.as_bytes());
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
// 解析 refresh_token,返回 (user_id, expires_at)
|
||||
#[allow(dead_code)]
|
||||
pub fn verify_refresh_token(token: &str, _secret: &str) -> Result<(i32, i64), String> {
|
||||
let decoded = BASE64.decode(token)
|
||||
.map_err(|e| format!("Refresh token 格式错误: {}", e))?;
|
||||
|
||||
let payload = String::from_utf8(decoded)
|
||||
.map_err(|_| "Refresh token 解析失败".to_string())?;
|
||||
|
||||
let parts: Vec<&str> = payload.split(':').collect();
|
||||
if parts.len() != 3 {
|
||||
return Err("Refresh token 结构错误".to_string());
|
||||
}
|
||||
|
||||
let user_id: i32 = parts[0].parse()
|
||||
.map_err(|_| "Refresh token user_id 解析失败".to_string())?;
|
||||
let exp: i64 = parts[1].parse()
|
||||
.map_err(|_| "Refresh token exp 解析失败".to_string())?;
|
||||
|
||||
let now = Utc::now().timestamp();
|
||||
if now > exp {
|
||||
return Err("Refresh token 已过期".to_string());
|
||||
}
|
||||
|
||||
Ok((user_id, exp))
|
||||
// 生成 refresh_token(随机 UUID,不含任何敏感信息)
|
||||
// 身份验证通过数据库查询该 token 是否存在实现
|
||||
pub fn generate_refresh_token(_user_id: i32, _secret: &str) -> Result<String, String> {
|
||||
Ok(Uuid::new_v4().to_string())
|
||||
}
|
||||
|
||||
// 验证并解析JWT的函数
|
||||
|
||||
Reference in New Issue
Block a user