Rust全栈登录功能:JWT生成及字段缺失问题求助
解决方案:Rust Web应用登录流程的两个核心问题处理
问题1:登录时无法获取用户ID生成JWT
登录阶段获取用户ID的核心逻辑是通过用户名/密码从数据库查询完整的用户实例,你的verify_user_credentials函数需要确保返回包含ID的用户结构体,而不是仅验证密码不返回用户数据。
修复步骤:
- 确保
verify_user_credentials函数查询数据库时返回完整用户(包含ID):
use diesel::prelude::*; use crate::models::User; // 这个User结构体必须包含id字段 use crate::schema::users::dsl::*; use bcrypt; pub fn verify_user_credentials( username_input: &str, password_input: &str, db_conn: &PgConnection ) -> Result<User, Box<dyn std::error::Error>> { // 从数据库查询匹配用户名的用户(包含id) let user = users .filter(username.eq(username_input)) .first::<User>(db_conn)?; // 验证密码 if bcrypt::verify(password_input, &user.password_hash)? { Ok(user) } else { Err("Invalid password".into()) } }
- 在登录接口中调用该函数,直接从返回的
User实例中取id生成JWT:
use rocket::serde::json::Json; use rocket::http::Status; use jsonwebtoken::{encode, Header, Algorithm, EncodingKey}; use crate::models::{LoginUser, ResponseUser, User}; use crate::db::DbConn; #[post("/login", data = "<login_data>")] pub async fn login( login_data: Json<LoginUser>, db_conn: DbConn ) -> Result<Json<ResponseUser>, Status> { let user = db_conn.run(|c| { verify_user_credentials(&login_data.username, &login_data.password, c) }).await.map_err(|_| Status::Unauthorized)?; // 使用user.id生成JWT let token = encode( &Header::new(Algorithm::HS256), &serde_json::json!({"user_id": user.id}), &EncodingKey::from_secret("your_secret_key".as_ref()) ).map_err(|_| Status::InternalServerError)?; Ok(Json(ResponseUser { id: user.id, username: user.username, token })) }
问题2:Rocket解析LoginUser失败 & 前端无法解析ResponseUser
后端解析失败原因:
你的LoginUser结构体定义了id字段,但前端登录请求体里只需要传用户名和密码,不需要id,导致Rocket反序列化时找不到该字段报错。
修复LoginUser结构体:
use serde::Deserialize; // 登录请求只需要用户名和密码,去掉id字段或者标记为反序列化时跳过 #[derive(Debug, Deserialize)] pub struct LoginUser { pub username: String, pub password: String, // 如果必须保留id字段,添加以下属性让Rocket忽略反序列化时的缺失 // #[serde(skip_deserializing)] // pub id: Option<i32>, }
前端无法解析ResponseUser原因:
前端Yew中的ResponseUser结构体与后端返回的JSON字段不匹配,或者后端返回格式错误。
修复前端结构体定义:
确保字段名、类型完全匹配后端的ResponseUser:
use serde::Deserialize; #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct ResponseUser { pub id: i32, pub username: String, pub token: String, }
同时检查前端请求代码,确保提交的是正确的JSON格式(仅含username和password):
// Yew中提交登录请求的示例代码 let login_request = serde_json::json!({ "username": username, "password": password }); let response = reqwest::Client::new() .post("/api/login") .json(&login_request) .send() .await? .json::<ResponseUser>() .await?;
内容的提问来源于stack exchange,提问作者apoorv569
相关产品推荐
相关产品推荐

