使用了jwt作为身份验证和分发

This commit is contained in:
2025-09-26 13:48:18 +08:00
parent 4f0a171366
commit 1c2eb82248
5 changed files with 217 additions and 76 deletions

81
src/auth.rs Normal file
View File

@@ -0,0 +1,81 @@
use chrono::Utc;
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode};
use crate::models::Claims;
use actix_web::{
Error, HttpMessage, body::MessageBody, dev::ServiceRequest, dev::ServiceResponse,
middleware::Next,
}; // 新增:用于包装中间件函数
// 中间件函数:泛型 B 约束为 MessageBody返回 Result<ServiceResponse<B>, Error>
pub async fn jwt_middleware<B: MessageBody>(
req: ServiceRequest,
next: Next<B>,
) -> Result<ServiceResponse<B>, Error> {
// (保持原有逻辑不变)
let auth_header = req
.headers()
.get("Authorization")
.ok_or_else(|| actix_web::error::ErrorUnauthorized("缺少Authorization头"))?
.to_str()
.map_err(|_| actix_web::error::ErrorUnauthorized("Authorization格式无效"))?;
let token = auth_header.strip_prefix("Bearer ").ok_or_else(|| {
actix_web::error::ErrorUnauthorized("Authorization格式应为 Bearer <token>")
})?;
let jwt_secret = std::env::var("JWT_SECRET")
.map_err(|_| actix_web::error::ErrorInternalServerError("服务器未配置JWT密钥"))?;
let claims = verify_token(token, &jwt_secret)
.map_err(|e| actix_web::error::ErrorUnauthorized(format!("无效的token: {}", e)))?;
req.extensions_mut().insert(claims);
next.call(req).await
}
// 生成JWT的函数
pub fn generate_token(
user_id: i32,
openid: &str,
user_type: i32,
secret: &str,
) -> Result<String, String> {
// 设置过期时间:当前时间 + 24小时86400秒
let now = Utc::now();
let exp = (now + chrono::Duration::hours(24)).timestamp();
let iat = now.timestamp();
// 构建Claims
let claims = Claims {
exp,
iat,
user_id,
openid: openid.to_string(),
user_type,
};
// 生成token
encode(
&Header::new(Algorithm::HS256), // 使用HS256算法
&claims,
&EncodingKey::from_secret(secret.as_bytes()), // 签名密钥
)
.map_err(|e| format!("生成JWT失败: {}", e))
}
// 验证并解析JWT的函数
pub fn verify_token(token: &str, secret: &str) -> Result<Claims, String> {
// 验证配置指定算法默认会检查exp等字段
let validation = Validation::new(Algorithm::HS256);
// 解析token
let decoded = decode::<Claims>(
token,
&DecodingKey::from_secret(secret.as_bytes()), // 与签发时相同的密钥
&validation,
)
.map_err(|e| format!("JWT验证失败: {}", e))?;
Ok(decoded.claims)
}