首页 > 其他分享 >axum处理cookie

axum处理cookie

时间:2023-11-02 09:57:35浏览次数:37  
标签:axum 登录 处理 用户 COOKIE Cookie cookie

Cookie 是通过 HTTP Header 进行传递的。由某个响应头进行设置,然后其它请求头就可以获取到了。本章将通过模拟用户中心来用 axum 操作 HTTP Header 演示 Cookie 的读写操作。

本章示例将实现以下路由:

路由说明
GET / 用户中心首页。如果用户未登录,显示提示信息;如果用户已登录,显示欢迎信息
GET /login 用户登录表单
POST /login 用户登录处理。如果用户名和密码正确,设置 Cookie 并跳转到用户中心首页
GET /logout 退出登录

为了突出重点,用户登录表单就不在这里展示了,你可以通过源代码查看。

用户登录

获取用户通过表单提交的登录信息,如果用户名和密码都正确,则设置 Cookie 并跳转到用户中心首页。代码如下:

async fn user_login_action(Form(frm): Form<UserLoginForm>) -> (StatusCode, HeaderMap, ()) {
    let mut headers = HeaderMap::new();
    if !(&frm.username == "axum.rs" && &frm.password == "axum.rs") {
        headers.insert(
            axum::http::header::LOCATION,
            "/login?msg=用户名或密码错误".parse().unwrap(),
        ); // 跳转到登录页面
    } else {
        let cookie = format!("{}={}", COOKIE_NAME, frm.username);
        headers.insert(
            axum::http::header::SET_COOKIE,
            cookie.as_str().parse().unwrap(),
        ); // 设置Cookie
        headers.insert(axum::http::header::LOCATION, "/".parse().unwrap()); // 跳转到用户中心首页
    }
    (StatusCode::FOUND, headers, ())
}

该处理函数的参数是一个表单结构体,其中包含了用户提交的用户名和密码。

首先,检查用户名和密码是否是axum.rs,如果不是,跳转到用户登录的表单页面,并附带提示信息。

如果用户名和密码正确,先设置 Cookie,注意,设置 Cookie 的 Header 名是 SET_COOKIE;然后跳转到用户中心首页。

用户中心首页

对于未登录的用户,用户中心首页将提示错误信息。相应的,对于已登录用户,则从 Cookie 取出登录用户的用户名,并显示欢迎信息。

async fn user_center(headers: HeaderMap) -> Result<Html<String>, &'static str> {
    let cookies = headers
        .get(axum::http::header::COOKIE)
        .and_then(|v| v.to_str().ok())
        .map(|v| v.to_string())
        .unwrap_or("".to_string()); // 从请求头获取所有COOKIE
    if cookies.is_empty() {
        return Err("NO COOKIE SETTED"); // 没有 Cookie
    }
    let mut logined_username: Option<String> = None;
    let cookies: Vec<&str> = cookies.split(';').collect(); // 多个cookie用;分割
    for cookie in cookies {
        let cookie_pair: Vec<&str> = cookie.split('=').collect(); // 每个cookie都是用=分割的键值对
        let cookie_name = cookie_pair[0].trim();
        let cookie_value = cookie_pair[1].trim();
        // 如果 cookie 的名称是我们希望的,并且值不为空
        if cookie_name == COOKIE_NAME && !cookie_value.is_empty() {
            logined_username = Some(String::from(cookie_value)); // 设置已登录用户的用户名
            break;
        }
    }
    if logined_username.is_none() {
        return Err("COOKIE IS EMPTY"); // 没有我们需要的cookie
    }
    let html = format!(
        r#"
        <!DOCTYPE html>
        <html lang="zh-Hans">
          <head>
            <meta charset="utf-8" />
            <meta name="author" content="axum.rs ([email protected])" />
            <title>
              用户中心-AXUM中文网
            </title>
          </head>
          <body>
          <p>你好,<strong>{}</strong>!你已成功登录。[<a href="/logout">退出登录</a>]
          </body>
          </html>
        "#,
        logined_username.unwrap()
    );
    Ok(Html(html))
}

因为我们要通过 HTTP Header 获取 Cookie,所以该处理器的参数是一个包含所有 Header 的集合。

首先,获取 Cookie。如果 HTTP Header 中没有 Cookie,直接返回错误信息。和写入不同,读取 Cookie 时,使用的 Header 名是 COOKIE

接着检查已设置的 Cookie。在 HTTP Header 中,Cookie 的形式是这样的:cookie1=value1;cookie2=value2。所以先通过;将 Header 中的 Cookie 信息拆分成一个个键值对,然后再对键值对进行=拆分,这样就能得到 Cookie 的名称和值。

遍历已拆分的 Cookie,如果名称是我们期望的,并且值不为空,说明用户已登录,这时候返回欢迎信息;相反,返回错误信息。

退出登录

退出登录也是设置 Cookie,只是把 Cookie 的值设置为空。

async fn user_logout() -> (StatusCode, HeaderMap, ()) {
    let cookie = format!("{}=", COOKIE_NAME);
    let mut headers = HeaderMap::new();
    headers.insert(
        axum::http::header::SET_COOKIE,
        cookie.as_str().parse().unwrap(),
    ); // 清空Cookie
    headers.insert(axum::http::header::LOCATION, "/login".parse().unwrap()); // 跳转到登录页面
    (StatusCode::FOUND, headers, ())
}

本章通过一个模拟的用户中心演示了如何读写 Cookie。完整代码可以在我们的代码库中找到。

Cookie 中间件

还记得吗?我们在讲解中间件时说过,axum 直接使用了 tower 的中间件生态。tower-cookies是一个可以用于 axum 的 Cookie 中间件。

思考题

  1. 在登录的时候,如果用户输入的用户名或密码错误,会跳转到登录表单页面,并附带一个提示信息。我们并没有获取这个提示信息并进行处理。请你动动手,获取并处理这个提示信息。

  2. 回想一下在讲解 axum 请求时,我们说到 axum 提供了TypedHeader来简化操作,试试看能不能用它来简化 Cookie 的读取。

标签:axum,登录,处理,用户,COOKIE,Cookie,cookie
From: https://www.cnblogs.com/pythonClub/p/17804732.html

相关文章

  • axum 操作 redis
    通过 redis-rs 这个crate,可以很方便的操作redis。它提供了同步和异步两种连接,由于我们要集成到axum中,所以这里使用异步连接。本章将展示如何获取redis异步连接、如何将字符串保存到redis、如何获取到保存在redis里的字符串以及如何通过redis保存和读取自定义结构体。......
  • axum处理静态文件
    和其它Web框架一样,axum也会对所有请求进行处理。对于CSS、JS及图片等静态文件,并不需要axum的handler进行处理,而是只需要简单的把它们的内容进行返回即可。axum提供了处理静态文件的中间件。首先,我们创建一个名为 static 的目录,并在其中创建一个 axum-rs.txt 的文......
  • axum的状态共享
    状态共享是指,在整个应用或不同路由之间,共享一份数据。axum提供了方便的状态共享机制,但可能也会踩坑。本章将带你学习如何在axumweb应用中共享状态。如何进行状态共享axum使用 Layer 来实现状态共享。定义路由时,使用 layer() 加入要共享的数据,在需要获取该共享数据的......
  • vue打包后导致css属性值丢失的问题如何处理?
    当使用Vue进行打包时,有时可能会出现CSS属性值丢失的问题。这通常是由于CSS的压缩和优化过程导致的。下面是一些可能的解决方案:关闭CSS的压缩和优化:在Vue的配置文件(vue.config.js)中,你可以通过添加以下配置来关闭CSS的压缩和优化:module.exports={css:{extract:false,......
  • Xilinx VIvado学习-01 数值处理之除法(有符号)
    Verilog数值处理,在处理除法的时候,需要注意位宽。实例: quotient=a/b; reside=a%b; modulesi_div(inputsigned[9:0]a,inputsigned[7:0]b,outputsigned[9:0]quotient,outputsigned[7:0]reside);assignquotient=a/b;assignreside=a%b;endmodule......
  • Python自动化处理Excel数据
    需求描述:数据格式如下所示,需要分离出2023年7月1号之后的数据明细数据核对与处理:从Excel文件中提取特定日期后的签收数据1.引言在实际数据处理和分析过程中,经常会遇到需要从大量数据中提取出特定日期范围内的信息的需求。本文将介绍如何使用Python的pandas库来处理Excel文件,并......
  • 后端处理一个较大的json文件返回数据给前端太慢该如何优化?
    要优化后端处理较大JSON文件并提高返回数据给前端的速度,可以尝试以下几种方法:优化数据库查询:如果你的后端从数据库中提取数据并将其转换为JSON格式,可以优化数据库查询来提高效率。确保使用适当的索引和优化查询语句。逐步加载数据:将大型JSON文件分割成较小的块,并使用分页或滚动加载......
  • 异常处理(统一接口返回)
    异常处理统一#统一接口返回#自定义异常方法,替换掉全局#写一个方法#自定义异常处理的方法fromrest_framework.viewsimportexception_handlerfromrest_framework.responseimportResponsefromrest_frameworkimportstatusdefmy_exception_handler(exc,contex......
  • Json数据文件处理中遇到的一些问题总结(C++)
    一、海量数据处理的方法总结参考CSDN技术贴:海量数据处理方法C++面试必备-海量数据处理二、快速Json文件解析的库字节-json快速解析库三、无锁队列C++无锁队列四、C++打包静态库静态库和动态库Linux-(C/C++)生成并使用静态库/动态库c/c++依赖静态库、动态库符号问题在远......
  • 10、SpringMVC之处理Ajax请求
    创建名为spring_mvc_ajax的新module,过程参考9.1节和9.5节10.1、SpringMVC处理Ajax请求10.1.1、页面请求示例<inputtype="button"value="测试SpringMVC处理Ajax请求"onclick="testAjax()"><scripttype="text/javascript">functiontestA......