Rust登录注册模块
【摘要】 Rust登录注册模块
Rust04-登录注册模块
用户模块的介绍
接下来我们用 actix-web + sqlx + MySQL
写一个完整的用户注册登录模块
👉 用户模块
先来看看我们的模块结构是什么样子的
src/
├── main.rs
├── database/
│ └── mod.rs
└── modules/
├── mod.rs
└── user/
├── mod.rs
├── routes.rs
├── models.rs # 用户数据模型
├── services.rs # 业务逻辑
└── handlers.rs # 处理函数(可选)
🍎配置插件bcrypt
Cargo.toml
之中添加依赖插件
bcrypt = "0.15"
🍎main.rs
注册模块
在main.rs
入口文件之中引入模块
mod common {
pub mod response;
}
mod modules {
pub mod user;
}
use actix_cors::Cors;
use actix_web::{App, HttpServer, Responder,HttpResponse,web};
use dotenv::dotenv;
use sqlx::MySqlPool;
use std::env;
async fn welcome() -> impl Responder {
let addr = "127.0.0.1:8080/api";
println!("服务已经启动,数据库已连接,地址为:{}", addr);
HttpResponse::Ok().body(format!("欢迎访问NexusRust API,服务地址:{}", addr))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok(); // 一定要在读取环境变量之前调用
let database_url = env::var("DATABASE_URL").unwrap(); // 获取数据库连接字符串
let pool = MySqlPool::connect(&database_url).await.unwrap();
HttpServer::new(move || {
let cors = Cors::default()
.allow_any_origin()
.allow_any_method()
.allow_any_header(); // 允许所有来源
App::new()
// 添加 CORS 中间件
.wrap(cors)
// 2. 注入数据库连接池
.app_data(web::Data::new(pool.clone()))
// 3. 注册模块路由加前缀
.service(
web::scope("/api") // 这里加上 /api 前缀
.configure(modules::user::routes::config),
)
// 3. 注册路由
.route("/", web::get().to(welcome))
})
.bind("127.0.0.1:8888")?
.run()
.await
}
🍎user=>mod.rs
模块入口
组织声明子模块,在模块入口文件之中进行声明组织子模块
pub mod handlers;
pub mod models;
pub mod routes; // 必须有这一行,否则无法使用路由
🍎models.rs
声明该模块对应的数据库字段的类型,当然了,这个并不是必须的,更像是我们数据的类型
// # 用户数据模型
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct User {
pub id: i64,
pub name: String,
pub email: String,
}
👉用户注册/register
接下来我们开始从用户注册接口写我们的整个服务部分,一开始可能会略微简单一些,到后面我们不断的进行优化和升级
🍎src\modules\user\routes.rs
先添加我们的路由接口
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.route("/register", web::post().to(crate::modules::user::handlers::register_users));
cfg.route("/users", web::get().to(crate::modules::user::handlers::get_all_users));
}
🍎src\common\response.rs
添加一个公共模块存放我们返回的数据类型
use serde::Serialize;
#[derive(Serialize)]
pub struct ApiResponse {
pub code: i32,
pub msg: &'static str,
}
🍎 在main.rs
之中声明
mod common {
pub mod response;
}
🍎 在handlers.rs
之中定义并使用
引入
use crate::common::response::ApiResponse;// 导入 ApiResponse 模型
使用
// use crate::modules::user::models::ApiResponse;
use bcrypt::{hash, DEFAULT_COST};
// use serde::Serialize;
use crate::common::response::ApiResponse;// 导入 ApiResponse 模型
// 注册请求体
#[derive(serde::Deserialize)]
pub struct RegisterRequest {
pub username: String,
pub password: String,
// 其他字段可选
}
// use actix_web::web;
pub async fn register_users(
pool: web::Data<MySqlPool>,
form: web::Json<RegisterRequest>,
) -> HttpResponse {
// 检查用户名是否已存在
let exists: (i64,) = match sqlx::query_as("SELECT COUNT(*) FROM sys_user WHERE username = ?")
.bind(&form.username)
.fetch_one(pool.get_ref())
.await
{
Ok(count) => count,
Err(_) => {
return HttpResponse::InternalServerError().json(ApiResponse {
code: 500,
msg: "数据库错误",
})
}
};
if exists.0 > 0 {
return HttpResponse::Ok().json(ApiResponse {
code: 400,
msg: "用户名已存在",
});
}
// 密码加密
let hashed_pwd = match hash(&form.password, DEFAULT_COST) {
Ok(pwd) => pwd,
Err(_) => {
return HttpResponse::InternalServerError().json(ApiResponse {
code: 500,
msg: "密码加密失败",
})
}
};
// 插入新用户
let result = sqlx::query("INSERT INTO sys_user (username, password) VALUES (?, ?)")
.bind(&form.username)
.bind(&hashed_pwd)
.execute(pool.get_ref())
.await;
match result {
Ok(_) => HttpResponse::Ok().json(ApiResponse {
code: 200,
msg: "注册成功",
}),
Err(e) => {
eprintln!("注册失败: {:?}", e);
HttpResponse::InternalServerError().json(ApiResponse {
code: 500,
msg: "注册失败",
})
}
}
}
🍎测试接口
//成功的时候返回
{
"code": 200,
"msg": "注册成功"
}
//失败的时候返回的数据
{
"code": 400,
"msg": "用户名已存在"
}
👉用户登录/login
接下来我们开始写我们登录的接口模块
🍎src\modules\user\routes.rs
先添加我们的路由接口,还是在我们之前的文件之中
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.route("/register", web::post().to(crate::modules::user::handlers::register_users));
cfg.route("/login", web::post().to(crate::modules::user::handlers::login_users));
}
🍎 在handlers.rs
之中引入
use bcrypt::{hash, DEFAULT_COST};// 导入 bcrypt 库
编写登录接口
// 登录接口
pub async fn login_users(
pool: web::Data<MySqlPool>,
form: web::Json<LoginRequest>,
) -> HttpResponse {
// 查询用户
let user = sqlx::query_as::<_, User>("SELECT * FROM sys_user WHERE username = ?")
.bind(&form.username)
.fetch_one(pool.get_ref())
.await;
let user = match user {
Ok(u) => u,
Err(_) => {
return HttpResponse::Ok().json(ApiResponse {
code: 400,
msg: "用户名或密码错误",
});
}
};
// 校验密码
let is_valid = verify(&form.password, &user.password).unwrap_or(false);
if is_valid {
HttpResponse::Ok().json(ApiResponse {
code: 200,
msg: "登录成功",
})
} else {
HttpResponse::Ok().json(ApiResponse {
code: 400,
msg: "用户名或密码错误",
})
}
}
🍎测试接口
// 失败的时候返回格式
{
"code": 400,
"msg": "用户名或密码错误"
}
//成功的时候返回格式
{
"code": 200,
"msg": "登录成功"
}
登录接口ok
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)