当前位置: 首页 > news >正文

【Rust基础】使用Rocket从Token中提取用户信息

概要

Rocket没有像Spring那样提供了ContextHolder来直接获取当前请求对象,我们目前也不能直接通过一个静态工具类来获取请求对象,因为它是基于协程而不是线程的,所以我们只能通过接口中从request中提取需要的数据,作为函数参数传递下去。

Rocket提供了FromRequest这个trait,通过它可以拿到原始的request对象,从而返回我们需要的数据。

从Token中提取用户信息

用户登录后,将返回一个Token给客户端,客户端请求时将Token放到Header中,服务端从Token解析用户信息,这个Token可以是简单UUID,也可以是JWT等。我们可以从Request中提取这些Token。

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserPrincipal {/// 用户IDpub id: i64,/// 昵称pub nickname: String,
}#[rocket::async_trait]
impl<'r> FromRequest<'r> for UserPrincipal {type Error = &'r str;async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {// 从header提取Tokenlet user_info = req.headers().get("Token").next().and_then(|token| {// 从redis获取tokenlet user = cache::get::<UserPrincipal>(&format!("{}{}",CachePrefix::AccessToken.to_string(),token));if user.is_none() {return None;}let user = user.unwrap();Some(UserPrincipal {id: user.id.clone(),nickname: user.nickname.clone(),})});let user = match user_info {Some(user) => user,None => return Outcome::Error((Status::Unauthorized, "未登录")),};// 使用user验证其他场景Outcome::Success(user)}
}

以上,我们定义了一个UserPrincipal作为在系统中关联的用户认证主体,通过FromRequest从Header拿到Token后,再去redis中查询用户信息,如果未拿到则说明token已失效需要重新登录,返回401。

请求上下文

之前提到,我们无法直接拿到请求上下文,那我们可以自定义一个上下文,通过FromRequest这个trait来组装需要的数据。

例如:

pub struct ReqContext {/// 是否移动端pub is_mobile: bool,// 其他需要提取的数据
}#[rocket::async_trait]
impl<'r> FromRequest<'r> for ReqContext {type Error = ();async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {let re = Regex::new(MOBILE_USER_AGENT_REGEX).expect("Invalid regex");let user_agent = req.headers().get_one("User-Agent").unwrap_or("");Outcome::Success(ReqContext {is_mobile: re.is_match(user_agent),})}
}

这样以来,我们就可以在API中使用他们了。

#[post("/api", data = "<req>")]
pub async fn buy_member_card(req: Json<SomeData>,user: UserPrincipal,req_context: ReqContext,
) -> Res<OrderCreateRes> {match service::some_fn(req, user, req_context).await {Ok(res) => Res::success(res),Err(e) => Res::from_error(e),}
}

Rocket关闭时释放资源

对于一些连接池,我们需要在系统即将关闭的时候释放某些连接,或者等待未处理完成的数据处理完成后再关闭,Rocket提供了一个Fairing trait,可以attach自定义的Fairing来监听shutdown事件,从而实现释放资源。

pub struct ShutdownFairing;
#[rocket::async_trait]
impl Fairing for ShutdownFairing {fn info(&self) -> Info {Info {name: "Shutdown Handler",kind: Kind::Shutdown,}}async fn on_shutdown(&self, _rocket: &Rocket<Orbit>) {//释放资源}
}

需要注意的是:

  • 释放资源时,不要存在阻塞操作,否则会导致进程阻塞而无法关闭程序。
  • 对于kill -9可能无法正确释放资源,尽量不要强制kill。

相关文章:

  • (mac)Grafana监控系统之监控Linux的Redis
  • Java基础类库常用类库 java.lang、java.util
  • 奇异递归模板设计模式-CRTP
  • Retinex系列图像/视频增强算法介绍
  • Docker Registry(镜像仓库)
  • Java开发软件
  • C++项目 —— 基于多设计模式下的同步异步日志系统(5)(单例模式)
  • Gen - CDPT举例说明:动态上下文前缀(输入先和标签结合,输出结果会更贴近标签内容)
  • 【ROS】航点导航功能
  • 解决vscode找不到Python自定义模块,报错No module named ‘xxx‘
  • 【Redis】Redis中的常见数据类型(一)
  • 通过爬虫方式实现头条号发布视频(2025年4月)
  • 常见的页面报错
  • Spring MVC 如何体现 Model-View-Controller 各自的职责?它们之间是如何协作的?
  • VS Code 远程连接服务器:Anaconda 环境与 Python/Jupyter 运行全指南。研0大模型学习(第六、第七天)
  • LicheeRV Nano 与Ubuntu官方risc-v 镜像混合
  • xss学习3之服务端session
  • 大数据开发知识1:数据仓库
  • Java表达式1.0
  • 相对路径和绝对路径解析
  • 经济日报金观平:拥抱中国就是拥抱确定性
  • “万人大院”重组,上海交大校长丁奎岭:人才培养事关生存发展,再难也要改
  • “一城双白金”就在脚下!这场半马将以最高标准打造
  • 轻流科技薄智元:AI时代,打造“工业智造”需要“共生式进化”
  • 释新闻|特朗普喊话鲍威尔早点走人,美国总统能否解雇美联储主席?
  • 全国首票海关特殊监管区域外保税再制造业务落地上海